bzoj3339
线段树+离线
这种题既可以用莫队做也可以用线段树做,跟hh的项链差不多
首先我们处里出前缀mex,也就是1->i的mex值,再预处理出每个数下一次出现的位置,然后把每个前缀mex插入线段树,每个节点表示l==r表示1->l的mex,然后把询问按左端点排序,依次查询,修改每次把小于当前左端点的数的影响去除,也就是把i->nxt[i-1]的mex和a[i]取min,因为这些前缀mex的a[i]消失了,那么取min就是新答案,每次查询就是单点查询,也就是查询1->r的前缀mex,因为1-l-1的影响都被消除了,所以现在1-r的答案就是l-r的答案
#include<bits/stdc++.h> using namespace std; const int N = 200010, inf = 0x3f3f3f3f; struct query_ { int l, r, id; bool friend operator < (query_ A, query_ B) { return A.l < B.l; } } q[N]; int n, m; int nxt[N], tree[N << 2], tag[N << 2], a[N], ans[N], vis[N], last[N]; void pushdown(int x) { if(tag[x] == inf) return; tag[x << 1] = min(tag[x << 1], tag[x]); tag[x << 1 | 1] = min(tag[x << 1 | 1], tag[x]); tree[x << 1] = min(tree[x << 1], tag[x]); tree[x << 1 | 1] = min(tree[x << 1 | 1], tag[x]); tag[x] = inf; } void update(int l, int r, int x, int a, int b, int mn) { if(l > b || r < a) return; if(l >= a && r <= b) { tag[x] = min(tag[x], mn); tree[x] = min(tree[x], mn); return; } pushdown(x); int mid = (l + r) >> 1; update(l, mid, x << 1, a, b, mn); update(mid + 1, r, x << 1 | 1, a, b, mn); tree[x] = min(tree[x << 1], tree[x << 1 | 1]); } int query(int l, int r, int x, int pos) { if(l == r) { // printf("l = %d r = %d pos = %d tree[%d] = %d\n", l, r, pos, x, tree[x]); return tree[x]; } pushdown(x); int mid = (l + r) >> 1; if(pos <= mid) return query(l, mid, x << 1, pos); else return query(mid + 1, r, x << 1 | 1, pos); } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= m; ++i) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i; sort(q + 1, q + m + 1); int pos = 0; memset(tree, 0x3f3f, sizeof(tree)); memset(tag, 0x3f3f, sizeof(tag)); for(int i = 1; i <= n; ++i) { nxt[last[a[i]]] = i; last[a[i]] = i; vis[a[i]] = 1; while(vis[pos]) ++pos; // printf("i = %d pos = %d\n", i, pos); update(1, n, 1, i, i, pos); } for(int i = 1; i <= n; ++i) if(nxt[i] == 0) nxt[i] = n + 1; pos = 1; for(int i = 1; i <= m; ++i) { while(pos < q[i].l && pos <= n) { update(1, n, 1, pos, nxt[pos] - 1, a[pos]); // printf("pos = %d nxt[%d] = %d a[%d] = %d\n", pos, pos, nxt[pos], pos, a[pos]); ++pos; } // printf("q[%d].l = %d q[%d].r = %d id = %d pos = %d\n", i, q[i].l, i, q[i].r, q[i].id, pos); ans[q[i].id] = query(1, n, 1, q[i].r); } for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]); return 0; }