1 条题解

  • 1
    @ 2023-8-3 9:56:18
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <map>
    #include <cstring>
    #include <iomanip>
    const int N = 1e6 + 10;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    
    //last[i]表示上一次i出现的位置 
    //cnt[i]表示以ai结尾时完美序列的起始位置 
    int n , m, last[2*N], cnt[200010] , a[200010] , dp[200010][30] , l , r; 
    void init()
    {
    	for(int j = 1; (1 << j) <= n; j++)
    	{
    		for(int i = 1; i + (1 << j) - 1 <= n; i++)
    			dp[i][j] = max(dp[i][j - 1] , dp[i + (1 << j - 1)][j - 1]);
    	}
    }
    
    int find(int l , int r)
    {
    	int k = log2(r - l + 1);
    	return max(dp[l][k] , dp[r - (1 << k) + 1][k]);	
    } 
    
    int finda(int l , int r )
    {
    	int key = l;
    	int ans = l - 1;
    	
    	while( l <= r)
    	{
    		int mid = l + r >> 1;
    		if(cnt[mid] < key)
    		{
    			ans = mid;
    			l = mid + 1;
    		}
    		else
    			r = mid - 1;
    	}
    	return ans;
    }
    
    int main()
    {
    	cin >> n >> m;
    	for(int i = 1; i <= n; i++)
    		scanf("%d" , &a[i]);
    	
    	//上一次a[1]出现的位置 
    	last[a[1] + N] = 1;
    	//以a1结尾时,完美序列的起始位置 
    	cnt[1] = 1;
    	//初始化dp
    	dp[1][0] = 1; 
    	
    	for(int i = 2; i <= n; i++)
    	{
    		//以a[i]结尾时的起点 
    		cnt[i] = max(cnt[i - 1] , last[a[i] + N] + 1);
    		dp[i][0] = i - cnt[i] + 1;//当前的最大长度
    		last[a[i] + N] = i;//更新当前数上一次出现的位置 
    	}
    	
    	init(); 
    	while( m-- )
    	{
    		scanf("%d%d" , &l , &r);
    		l++ , r++;//确定查找范围
    		int ans = finda(l , r);//找到的位置
    		int ans1 = ans - l + 1;
    		
    		//如果在区间内 
    		if(ans < r)
    			ans1 = max(ans1 , find(ans + 1, r));
    		
    		printf("%d\n" , ans1); 
    	}
    
    	return 0;
    }
    

    借鉴一下张老师的代码

    • 1

    信息

    ID
    451
    时间
    1000ms
    内存
    512MiB
    难度
    9
    标签
    递交数
    80
    已通过
    9
    上传者