链接:
http://acm.zzu.edu.cn:8000/problem.php?id=10508
题意:
给定一个序列,长度为N,每次询问为一组区间[Li,Ri],输出Li到Ri中出现恰好两次的不同数的个数.
题解:
先对a离散化一下,当然也可以不离散化,用map也行。离线做,按右端点排序,从1遍历到n,更新树状数组和ans
对于a数组,我们记录上一个和a[i]相等的位置last[i],更新树状数组不太好想,具体看代码
代码:
31 int n, m; 32 int a[MAXN]; 33 int last[MAXN]; 34 int pos[MAXN]; 35 int T[MAXN]; 36 int ans[MAXN]; 37 38 struct node { 39 int l, r, id; 40 bool operator< (const node &t) const { 41 if (r == t.r) return l < t.l; 42 return r < t.r; 43 } 44 }q[MAXN]; 45 46 void add(int i, int x) { 47 while (i <= n) T[i] += x, i += i&-i; 48 } 49 50 int sum(int i) { 51 int s = 0; 52 while (i) s += T[i], i -= i&-i; 53 return s; 54 } 55 56 int main() { 57 scanf("%d%d", &n, &m); 58 VI v; 59 rep(i, 1, n + 1) scanf("%d", a + i), v.pb(a[i]); 60 sort(all(v)); 61 v.erase(unique(all(v)), v.end()); 62 rep(i, 1, n + 1) a[i] = lower_bound(all(v), a[i]) - v.begin() + 1; 63 rep(i, 1, n + 1) last[i] = pos[a[i]], pos[a[i]] = i; 64 rep(i, 0, m) { 65 scanf("%d%d", &q[i].l, &q[i].r); 66 q[i].id = i; 67 } 68 sort(q, q + m); 69 int index = 0; 70 rep(i, 1, n + 1) { 71 int p = last[i]; 72 if (p) { 73 add(p, 1); 74 p = last[p]; 75 if (p) { 76 add(p, -2); 77 p = last[p]; 78 if (p) add(p, 1); 79 } 80 } 81 while (index < m && q[index].r == i) { 82 int x = sum(q[index].r) - sum(q[index].l - 1); 83 ans[q[index].id] = x; 84 index++; 85 } 86 } 87 rep(i, 0, m) printf("%d ", ans[i]); 88 return 0; 89 }