• LOJ10121 与众不同


    题目蓝链

    Solution

    首先要预处理出每一个位置的上一个与当前位置的数相同的位置,然后就可以利用它求出(pos[i]),表示以第(i)个数为结尾的最长完美序列的起始位置。然后就可以求出每一个位置往前最多可以选多少个数,我们用RMQ来维护一下这个东西

    询问的时候,由于(pos)单调不降,直接在([l, r])中二分一下找到最靠前的一个位置使得(pos[mid] > l),因为要保证选的数要在([l, r])的范围内。所以(ans = max(mid - l, Max(mid, r)))(Max(l, r))表示RMQ维护的最大值

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int maxn = 2e5 + 10;
    const int maxm = 2e6 + 10;
    
    int n, m;
    int lst[maxm], pos[maxn], f[maxn], Max[maxn][18], Pow[18], Log[maxn];
    
    int find(int l, int r) {
    	int L = l; /**/
    	while (l <= r) {
    		int mid = (l + r) >> 1;
    		if (pos[mid] > L) r = mid - 1;
    		else l = mid + 1;
    	}
    	return r + 1;
    }
    
    int query(int l, int r) {
    	int x = Log[r - l + 1];
    	return max(Max[r][x], Max[l + Pow[x] - 1][x]);
    }
    
    int main() {
    #ifdef xunzhen
    	freopen("perfect.in", "r", stdin);
    	freopen("perfect.out", "w", stdout);
    #endif
    
    	n = read(); m = read();
    
    	Pow[0] = 1;
    	for (int i = 1; i <= 17; i++) Pow[i] = Pow[i - 1] << 1;
    	for (int i = 2; i <= n; i++) Log[i] = Log[i >> 1] + 1;
    
    	for (int i = 1; i <= n; i++) {
    		int k = read() + (int)1e6;
    		pos[i] = max(pos[i - 1], lst[k] + 1);
    		lst[k] = i;
    		f[i] = i - pos[i] + 1;
    	}
    
    	for (int i = 1; i <= n; i++) {
    		Max[i][0] = f[i];
    		for (int j = 1; j <= 17; j++) {
    			int pre = max(i - Pow[j - 1], 0); /**/
    			Max[i][j] = max(Max[i][j - 1], Max[pre][j - 1]);
    		}
    	}
    
    	while (m--) {
    		int l = read() + 1, r = read() + 1;
    		int res = find(l, r), ans = res - l;
    		if (res <= r) ans = max(ans, query(res, r));
    		printf("%d
    ", ans);
    	}
    
    	return 0;
    }
    

    Summary

    这道题是真的坑 其实是我坑...

    这道题我不得不承认,还是有一点难度的

    RMQ一定要经常打一下,要不然会有很多细节写错

    (debug):打错的地方已在代码中(mark)

  • 相关阅读:
    SPF(poj 1523) 割点入门
    从一个例子讲解拷贝构造函数与return
    还是引用
    引用的实质
    const
    三目运算符
    关于C语言链表的学习
    CS2013调试DLL
    fread与fwrite的自我理解
    可见字符与不可见字符
  • 原文地址:https://www.cnblogs.com/xunzhen/p/9672739.html
Copyright © 2020-2023  润新知