题目已经没有了
思路:
莫队+分块
首先有一个结论:所有的答案都在0到n之间,用反正法就能证明,所以所有大于n的数都可以看成n
离线,对询问区间进行莫队,再对答案的范围0到n进行分块
复杂度(n+2*m)√n
代码:
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 2e5 + 5; int a[N], cnt[N], bl[N], ans[N], l[555], r[555], block[555], blo, n; struct node { int l, r, bl, id; bool operator < (const node & t) const { if(bl == t.bl) return r < t.r; else bl < t.bl; } }Q[N]; void add(int x) { if(!cnt[x]) block[bl[x]]++; cnt[x] ++; } void del(int x) { cnt[x]--; if(!cnt[x]) block[bl[x]]--; } int query() { int i; for (i = bl[0]; i <= bl[n]; i++) if(block[i] != r[i] - l[i] + 1) break; for (int j = l[i]; j <= r[i]; j++) if(!cnt[j]) return j; } int main() { int m; while(~scanf("%d%d", &n, &m)) { for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if(a[i] >= n) a[i] = n; } blo = sqrt(n+1); for (int i = 0; i <= n; i++) bl[i] = i/blo + 1; for (int i = bl[0]; i <= bl[n]; i++) { l[i] = (i-1)*blo; r[i] = min(i*blo-1, n); } blo = sqrt(n); for (int i = 1; i <= m; i++) { scanf("%d%d", &Q[i].l, &Q[i].r); Q[i].bl = (Q[i].l - 1)/blo + 1; Q[i].id = i; } sort(Q+1, Q+1+m); mem(cnt, 0); mem(block, 0); int l = 1, r = 0; for (int i = 1; i <= m; i++) { while(r < Q[i].r) r++, add(a[r]); while(r > Q[i].r) del(a[r]), r--; while(l < Q[i].l) del(a[l]), l++; while(l > Q[i].l) l--, add(a[l]); ans[Q[i].id] = query(); } for (int i = 1; i <= m; i++) printf("%d ", ans[i]); } return 0; }