[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=2743
[算法]
首先预处理nxt[]数组 , 其中 , nxt[i]表示下一个和i号位颜色相同的位置 , 然后离线 , 将询问按左端点排序 , 每次将nxt[i]减一 , nxt[nxt[i]]加一
用树状数组维护即可 , 详见代码
时间复杂度 : O(MlogN)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 10; struct Que { int l , r , id; } q[MAXN]; int n , c , m; int a[MAXN] , ans[MAXN] , pre[MAXN] , nxt[MAXN]; bool visited[MAXN]; struct Binary_Indexed_Tree { int c[MAXN]; inline int lowbit(int x) { return x & (-x); } inline void add(int pos,int value) { if (!pos) return; for (int i = pos; i <= n; i += lowbit(i)) c[i] += value; } inline int query(int pos) { int ret = 0; if (!pos) return 0; for (int i = pos; i; i -= lowbit(i)) ret += c[i]; return ret; } inline int query(int l,int r) { return query(r) - query(l - 1); } } bit; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline bool cmp(Que a,Que b) { return a.l < b.l; } int main() { read(n); read(c); read(m); for (int i = 1; i <= n; i++) read(a[i]); for (int i = n; i >= 1; i--) { if (!visited[a[i]]) { visited[a[i]] = true; pre[a[i]] = i; continue; } else { nxt[i] = pre[a[i]]; pre[a[i]] = i; } } memset(visited,false,sizeof(visited)); for (int i = 1; i <= n; i++) { if (!visited[a[i]]) { bit.add(nxt[i],1); visited[a[i]] = true; } } for (int i = 1; i <= m; i++) { read(q[i].l); read(q[i].r); q[i].id = i; } sort(q + 1,q + m + 1,cmp); int cur = 0; for (int i = 1; i <= m; i++) { while (cur < q[i].l) { bit.add(nxt[cur],-1); bit.add(nxt[nxt[cur]],1); ++cur; } ans[q[i].id] = bit.query(q[i].r) - bit.query(q[i].l - 1); } for (int i = 1; i <= m; i++) printf("%d ",ans[i]); return 0; }