BZOJ2120数颜色(树套树+set)
Posted Lukaluka
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2120数颜色(树套树+set)相关的知识,希望对你有一定的参考价值。
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2120
题解:http://blog.sina.com.cn/s/blog_6e63f59e0101bm87.html
一开始懒得离散化,跑了7000+ms23333 宛如一个智障,可是出现了这么迷醉的情况、
2333果然还是要勤快一点 写个离散化啊
#include <set> #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #define MaxN 20010 #define MaxM 7000010 using namespace std; int n, S = 0, m, tot = 0, N = 0; int num[MaxN], da[MaxN], map[MaxN]; int root[MaxN], t1[MaxN], t2[MaxN]; int ls[MaxM], rs[MaxM], sum[MaxM]; char s[10]; set <int> q[MaxN]; struct rec{ int l, r; char s[10]; }op[MaxN]; void Read_Data(){ scanf("%d%d", &n, &m); for (int i = 0; i < MaxN; i++) q[i].insert(n+1), q[i].insert(0); for (int i = 1; i <= n; i++) { scanf("%d", &num[i]); da[++tot] = num[i]; } for (int i = 1; i <= m; i++){ scanf("%s%d%d", op[i].s, &op[i].l, &op[i].r); if (op[i].s[0] != ‘Q‘) da[++tot] = op[i].r; } sort(da+1, da+1+tot); map[++N] = da[1]; for (int i = 2; i <= tot; i++) if (da[i] != da[i-1]) map[++N] = da[i]; } int find(int x){ int l = 1, r = N, mid; while (l < r) { mid = (l+r) >> 1; if (x <= map[mid]) r = mid; else l = mid+1; } return l; } void updata(int &x, int l, int r, int k, int c){ int fa = x; if (!x) x = ++S; ls[x] = ls[fa], rs[x] = rs[fa], sum[x] = sum[fa]+c; if (l == r) return; int mid = (l+r) >> 1; if (k <= mid) updata(ls[x], l, mid, k, c); else updata(rs[x], mid+1, r, k, c); } int lowbit(int x) { return x & (-x); } void updata(int x, int k, int c){ for (int i = x; i <= n; i += lowbit(i)) updata(root[i], 0, n, k, c); } int query(int a, int b, int k){ int l = 0, r = n, mid, ret = 0, len1 = 0, len2 = 0, t = 0; for (int i = a; i; i -= lowbit(i)) t1[++len1] = root[i]; for (int i = b; i; i -= lowbit(i)) t2[++len2] = root[i]; while (l < r){ mid = (l+r) >> 1; // cout<<a<<" "<<b<<" t"<<b-a<<" l"<<l<<" r"<<r<<endl; if (k <= mid) { r = mid; for (int i = 1; i <= len1; i++) ret -= sum[rs[t1[i]]]; for (int i = 1; i <= len2; i++) ret += sum[rs[t2[i]]]; for (int i = 1; i <= len1; i++) t1[i] = ls[t1[i]]; for (int i = 1; i <= len2; i++) t2[i] = ls[t2[i]]; } else { l = mid+1; for (int i = 1; i <= len1; i++) t1[i] = rs[t1[i]]; for (int i = 1; i <= len2; i++) t2[i] = rs[t2[i]]; } } return ret; } void Solve(){ int l, r, c; n++; for (int i = 1; i < n; i++) num[i] = find(num[i]), q[num[i]].insert(i); for (int i = 1; i < n; i++) updata(i, *q[num[i]].upper_bound(i), 1);//, updata(0, i, 1); // cout<<query(1, 6, 6); for (int i = 1; i <= m; i++){ int l = op[i].l, r = op[i].r; if (op[i].s[0] == ‘Q‘){ printf("%d\n", query(l-1, r, r)); } else { set<int>::iterator p; p = q[num[l]].lower_bound(l); p--; int t = *(p); if (t) { updata(t, l, -1); updata(t, *q[num[l]].upper_bound(l), 1); } updata(l, *q[num[l]].upper_bound(l), -1); q[num[l]].erase(l); num[l] = find(op[i].r); q[num[l]].insert(l); p = q[num[l]].lower_bound(l); p--; t = *(p); if (t) { updata(t, l, 1); updata(t, *q[num[l]].upper_bound(l), -1); } updata(l, *q[num[l]].upper_bound(l), 1); } } } int main(){ Read_Data(); Solve(); return 0; }
以上是关于BZOJ2120数颜色(树套树+set)的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ 720][JZYZOJ 2016]gty的妹子树 强制在线 树分块/树套树