[关闭]
@ljt12138 2017-05-28T18:17:56.000000Z 字数 13025 阅读 806

数据结构训练

可并堆

学习了一个斜堆的写法,非常好写,于是又去切了可并堆模板[Apio2012]dispatching:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. struct lheap {
  5. long long dat;
  6. int lc, rc;
  7. lheap() { lc = rc = 0; }
  8. } tree[MAXN*2];
  9. int tp = 0;
  10. int merge(int a, int b)
  11. {
  12. if (a == 0 || b == 0) return a+b;
  13. if (tree[a].dat < tree[b].dat) swap(a, b);
  14. swap(tree[a].lc, tree[a].rc);
  15. return tree[a].rc = merge(tree[a].rc, b), a;
  16. }
  17. long long pop(int &a)
  18. {
  19. long long ret = tree[a].dat;
  20. a = merge(tree[a].lc, tree[a].rc);
  21. return ret;
  22. }
  23. struct node {
  24. int to, next;
  25. } edge[MAXN];
  26. int head[MAXN], top = 0;
  27. inline void push(int i, int j)
  28. { edge[++top] = (node){j, head[i]}, head[i] = top; }
  29. int n;
  30. long long m, ans = 0;
  31. int b[MAXN];
  32. long long c[MAXN], l[MAXN];
  33. int rt;
  34. int dfs(int nd, long long &sig, int &cnt)
  35. {
  36. int tr = ++tp;
  37. long long sum; int ct;
  38. sig = tree[tr].dat = c[nd], cnt = 1;
  39. for (int i = head[nd]; i; i = edge[i].next)
  40. tr = merge(tr, dfs(edge[i].to, sum, ct)), sig += sum, cnt += ct;
  41. while (sig > m) sig -= pop(tr), cnt--;
  42. ans = max(ans, cnt*l[nd]);
  43. return tr;
  44. }
  45. int main()
  46. {
  47. scanf("%d%lld", &n, &m);
  48. for (int i = 1; i <= n; i++) {
  49. scanf("%d%lld%lld", &b[i], &c[i], &l[i]);
  50. if (b[i]) push(b[i], i);
  51. else rt = i;
  52. }
  53. long long t;
  54. int cnt;
  55. dfs(rt, t, cnt);
  56. printf("%lld\n", ans);
  57. return 0;
  58. }

bzoj1078: [SCOI2008]斜堆

结论题/找规律题,递归求解发现应该交替插入,然后只要分类讨论四种情况就好。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 105;
  4. int lc[MAXN], rc[MAXN], n;
  5. int solve(int nd, int a[], int &top)
  6. {
  7. top = 0;
  8. int l[MAXN], r[MAXN], ltop = 0, rtop = 0, lf = 0, rf = 0;
  9. if (lc[nd] != -1) solve(lc[nd], l, ltop);
  10. if (rc[nd] != -1) solve(rc[nd], r, rtop);
  11. if (ltop-rtop > 1) {
  12. while (ltop-lf > rtop-rf) a[++top] = l[++lf];
  13. a[++top] = nd;
  14. while (ltop-lf > 0) a[++top] = r[++rf], a[++top] = l[++lf];
  15. } else if (ltop == rtop+1) {
  16. a[++top] = nd;
  17. while (ltop-lf > 0) {
  18. a[++top] = l[++lf];
  19. if (rtop-rf > 0) a[++top] = r[++rf];
  20. }
  21. } else if (ltop == rtop) {
  22. a[++top] = nd;
  23. while (rtop-rf > 0)
  24. a[++top] = r[++rf], a[++top] = l[++lf];
  25. } else {
  26. while (rtop-rf > ltop-lf-1) a[++top] = r[++rf];
  27. a[++top] = nd;
  28. while (ltop-lf > 0) {
  29. a[++top] = l[++lf];
  30. if (rtop-rf > 0) a[++top] = r[++rf];
  31. }
  32. }
  33. }
  34. int main()
  35. {
  36. int a[MAXN], u;
  37. memset(lc, -1, sizeof lc);
  38. memset(rc, -1, sizeof rc);
  39. scanf("%d", &n);
  40. for (int i = 1; i <= n; i++) {
  41. scanf("%d", &u);
  42. if (u < 100) lc[u] = i;
  43. else rc[u-100] = i;
  44. }
  45. solve(0, a, u);
  46. for (int i = 1; i <= u; i++)
  47. printf("%d ", a[i]);
  48. return 0;
  49. }

bzoj4003: [JLOI2015]城池攻占

比较有意思的数据结构题。大概就是用可并堆维护还存活着的骑士,然后只需要lazy_tag就好了。

注意两种lazy_tag一定要考虑彼此的影响!

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 300005;
  4. struct sheap {
  5. pair<long long, int> dat;
  6. int lc, rc;
  7. long long tag1, tag2;
  8. sheap() { tag1 = 0, tag2 = 1; }
  9. } tree[MAXN*2];
  10. int tp = 0;
  11. long long a[MAXN], b[MAXN];
  12. int n, m;
  13. long long h[MAXN];
  14. long long s[MAXN];
  15. int c[MAXN], u;
  16. vector<int> v[MAXN];
  17. inline void pdw(int nd)
  18. {
  19. if (!nd) return;
  20. tree[nd].dat.first *= tree[nd].tag2;
  21. if (tree[nd].lc)
  22. tree[tree[nd].lc].tag2 *= tree[nd].tag2, tree[tree[nd].lc].tag1 *= tree[nd].tag2;
  23. if (tree[nd].rc)
  24. tree[tree[nd].rc].tag2 *= tree[nd].tag2, tree[tree[nd].rc].tag1 *= tree[nd].tag2;
  25. tree[nd].dat.first += tree[nd].tag1;
  26. if (tree[nd].lc) tree[tree[nd].lc].tag1 += tree[nd].tag1;
  27. if (tree[nd].rc) tree[tree[nd].rc].tag1 += tree[nd].tag1;
  28. tree[nd].tag1 = 0, tree[nd].tag2 = 1;
  29. }
  30. inline void mul_dt(int nd, long long dt)
  31. { if (!nd) return; tree[nd].tag2 *= dt, tree[nd].tag1 *= dt; }
  32. inline void plus_dt(int nd, long long dt)
  33. { if (!nd) return; tree[nd].tag1 += dt; }
  34. void tour(int nd, int tab = 0)
  35. {
  36. if (!nd) return;
  37. pdw(nd);
  38. tour(tree[nd].lc, tab+2), tour(tree[nd].rc, tab+2);
  39. }
  40. int merge(int a, int b)
  41. {
  42. if (a == b && a != 0) throw;
  43. pdw(a), pdw(b);
  44. if (a == 0 || b == 0) return a+b;
  45. if (tree[a].dat.first > tree[b].dat.first) swap(a, b);
  46. swap(tree[a].lc, tree[a].rc);
  47. return tree[a].lc = merge(tree[a].lc, b), a;
  48. }
  49. inline long long top_ele(int a)
  50. { return pdw(a), tree[a].dat.first; }
  51. inline void pop(int &a)
  52. {
  53. pdw(a);
  54. a = merge(tree[a].lc, tree[a].rc);
  55. }
  56. struct node {
  57. int to, next;
  58. } edge[MAXN];
  59. int head[MAXN], top = 0;
  60. inline void push(int i, int j)
  61. { edge[++top] = (node){j, head[i]}, head[i] = top; }
  62. int cnt[MAXN], depth[MAXN], death[MAXN];
  63. int dfs(int nd)
  64. {
  65. int hp = 0;
  66. for (int i = 0; i < v[nd].size(); i++) {
  67. hp = merge(hp, (tree[++tp].dat = make_pair(s[v[nd][i]], v[nd][i]), tp));
  68. }
  69. for (int i = head[nd]; i; i = edge[i].next) {
  70. depth[edge[i].to] = depth[nd]+1;
  71. hp = merge(hp, dfs(edge[i].to));
  72. }
  73. while (hp && top_ele(hp) < h[nd]) {
  74. pair<long long, int> dat = tree[hp].dat;
  75. death[dat.second] = nd, cnt[nd]++;
  76. pop(hp);
  77. }
  78. if (!hp) return hp;
  79. if (a[nd] == 0) plus_dt(hp, b[nd]);
  80. else mul_dt(hp, b[nd]);
  81. return hp;
  82. }
  83. int main()
  84. {
  85. scanf("%d%d", &n, &m);
  86. for (int i = 1; i <= n; i++) scanf("%lld", &h[i]);
  87. for (int i = 2; i <= n; i++)
  88. scanf("%d%lld%lld", &u, &a[i], &b[i]), push(u, i);
  89. for (int i = 1; i <= m; i++){
  90. scanf("%lld%d", &s[i], &c[i]);
  91. v[c[i]].push_back(i);
  92. }
  93. depth[1] = 1;
  94. dfs(1);
  95. for (int i = 1; i <= n; i++) printf("%d\n", cnt[i]);
  96. for (int i = 1; i <= m; i++) printf("%d\n", depth[c[i]]-depth[death[i]]);
  97. return 0;
  98. }

树状数组

bzoj4415: [Shoi2013]发牌

类似约瑟夫问题,树状数组上二分小trick,貌似一年前就在千古神犇lcy的课上学习过。就是二进制一位一位确定。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 700005;
  4. inline int lowbit(int i) { return i&(-i); }
  5. int c[MAXN], n;
  6. void modify(int pos, int dt)
  7. { for (int i = pos; i <= n; i += lowbit(i)) c[i] += dt; }
  8. int sum(int k)
  9. {
  10. int now = 0, dat = 0;
  11. for (int i = 1<<25; i; i >>= 1) {
  12. if (now+i <= n && dat+c[i+now] < k)
  13. dat += c[i+now], now += i;
  14. }
  15. return now+1;
  16. }
  17. int query(int a)
  18. {
  19. int ans = 0;
  20. for (int i = a; i; i -= lowbit(i))
  21. ans += c[i];
  22. return ans;
  23. }
  24. int main()
  25. {
  26. scanf("%d", &n);
  27. for (int i = 1; i <= n; i++) modify(i, 1);
  28. int now = 0;
  29. for (int i = 1; i <= n; i++) {
  30. int last = n-i+1, k;
  31. scanf("%d", &k);
  32. k += query(now) + 1;
  33. int p = k%last;
  34. if (p == 0) p = last;
  35. now = sum(p), modify(now, -1);
  36. printf("%d\n", now);
  37. }
  38. return 0;
  39. }

bzoj4418: [Shoi2013]扇形面积并

出题人大概没有学过高中数学...明明是均分之间的区间。

一开始还以为需要玄学可持久化,后来发现只需要在合适的地方打个表,然后一块一块扫过去,用树状数组kth就好。由于是寻找最大,可以通过变成最小。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 300005;
  4. int c[MAXN*10], n, m, k, r = 2000001;
  5. inline int lowbit(int i) { return i&(-i); }
  6. void modify(int nd, int dt)
  7. { for (int i = nd; i <= r; i += lowbit(i)) c[i] += dt; }
  8. int sum(int nd)
  9. { int ans = 0; for (int i = nd; i; i -= lowbit(i)) ans += c[i]; return ans; }
  10. int query(int l, int r)
  11. { return sum(r)-sum(l-1); }
  12. int kth(int nd)
  13. {
  14. int now = 0, dat = 0;
  15. for (int i = 1<<27; i; i >>= 1) {
  16. if (now+i <= r && dat+c[i+now] < nd)
  17. dat += c[i+now], now += i;
  18. }
  19. return now+1;
  20. }
  21. vector<int> add[MAXN*10];
  22. void solve()
  23. {
  24. long long ans = 0;
  25. for (int i = 1; i <= m; i++) {
  26. for (int j = 0; j < add[i].size(); j++) {
  27. if (add[i][j] > 0) modify(r-add[i][j]+1, 1);
  28. else modify(r-(-add[i][j])+1, -1);
  29. }
  30. long long rm = r-kth(k)+1;
  31. if (rm <= r) ans += rm*rm;
  32. }
  33. printf("%lld\n", ans);
  34. }
  35. int main()
  36. {
  37. scanf("%d%d%d", &n, &m, &k);
  38. m *= 2;
  39. for (int i = 1; i <= n; i++) {
  40. int r, a, b;
  41. scanf("%d%d%d", &r, &a, &b);
  42. if (a < 0) a += m;
  43. if (b < 0) b += m;
  44. if (a < b) add[a+1].push_back(r), add[b+1].push_back(-r);
  45. else if (a > b)
  46. add[1].push_back(r), add[b+1].push_back(-r), add[a+1].push_back(r);
  47. else add[1].push_back(r);
  48. }
  49. solve();
  50. return 0;
  51. }

bzoj1455: 罗马游戏

居然可以把死人和活人变成一组......昏君啊...

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 1000005;
  4. struct sheap {
  5. int lc, rc, dat;
  6. sheap() { lc = rc = 0; }
  7. } tree[MAXN];
  8. int merge(int a, int b)
  9. {
  10. if (a == 0 || b == 0) return a+b;
  11. if (tree[a].dat > tree[b].dat) swap(a, b);
  12. swap(tree[a].lc, tree[a].rc);
  13. return tree[a].lc = merge(tree[a].lc, b), a;
  14. }
  15. set<int> st;
  16. int pop(int &a)
  17. {
  18. int ret = tree[a].dat;
  19. st.insert(ret);
  20. a = merge(tree[a].lc, tree[a].rc);
  21. return ret;
  22. }
  23. int fa[MAXN];
  24. inline int findf(int nd)
  25. { return fa[nd]?fa[nd]=findf(fa[nd]):nd; }
  26. int n, m;
  27. char str[10];
  28. int htp[MAXN], dat[MAXN];
  29. int main()
  30. {
  31. scanf("%d", &n);
  32. for (int i = 1; i <= n; i++) scanf("%d", &tree[i].dat), dat[i] = tree[i].dat, htp[i] = i;
  33. scanf("%d", &m);
  34. for (int i = 1; i <= m; i++) {
  35. scanf("%s", str);
  36. if (str[0] == 'M') {
  37. int x, y;
  38. scanf("%d%d", &x, &y);
  39. if (st.count(dat[x]) || st.count(dat[y])) continue;
  40. x = findf(x), y = findf(y);
  41. if (x != y) fa[x] = y, htp[y] = merge(htp[x], htp[y]);
  42. } else {
  43. int x;
  44. scanf("%d", &x);
  45. if (st.count(dat[x])) puts("0");
  46. else
  47. printf("%d\n", pop(htp[findf(x)]));
  48. }
  49. }
  50. return 0;
  51. }

bzoj2006: [NOI2010]超级钢琴

堆+ST表。
堆维护表示从开始,终点在之间的区间最大值,每次取出最大值后将区间分裂。因此需要用ST表维护区间最大值和最大值位置。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005;
  4. long long f[MAXN][22];
  5. int pos[MAXN][22];
  6. long long a[MAXN];
  7. int n, k, l, r;
  8. inline long long max_val(int l, int r)
  9. {
  10. int k = int(log2(r-l+1)+0.0000001);
  11. return max(f[l][k], f[r-(1<<k)+1][k]);
  12. }
  13. inline int max_pos(int l, int r)
  14. {
  15. int k = int(log2(r-l+1)+0.0000001);
  16. if (f[l][k] >= f[r-(1<<k)+1][k]) return pos[l][k];
  17. return pos[r-(1<<k)+1][k];
  18. }
  19. struct query {
  20. int i, l, r;
  21. inline long long val()
  22. {
  23. return max_val(l, r)-a[i-1];
  24. }
  25. inline int pos()
  26. {
  27. return max_pos(l, r);
  28. }
  29. inline friend bool operator < (query a, query b)
  30. {
  31. return a.val() < b.val();
  32. }
  33. };
  34. priority_queue<query> hp;
  35. int main()
  36. {
  37. scanf("%d%d%d%d", &n, &k, &l, &r);
  38. for (register int i = 1; i <= n; i++)
  39. scanf("%lld", &a[i]), a[i] += a[i-1];
  40. for (register int i = 1; i <= n; i++) f[i][0] = a[i], pos[i][0] = i;
  41. for (register int j = 1; j <= 21; j++)
  42. for (register int i = 1; i <= n; i++) {
  43. f[i][j] = f[i][j-1], pos[i][j] = pos[i][j-1];
  44. if (i+(1<<(j-1)) <= n && f[i+(1<<(j-1))][j-1] > f[i][j]) {
  45. f[i][j] = f[i+(1<<(j-1))][j-1];
  46. pos[i][j] = pos[i+(1<<(j-1))][j-1];
  47. }
  48. }
  49. for (register int i = 1; i <= n; i++)
  50. if (i+l-1 <= n)
  51. hp.push((query){i, i+l-1, min(n, i+r-1)});
  52. long long ans = 0;
  53. for (register int i = 1; i <= k; i++) {
  54. query tp = hp.top(); hp.pop();
  55. ans += tp.val();
  56. int p = tp.pos();
  57. if (p-1 >= tp.l) hp.push((query){tp.i, tp.l, p-1});
  58. if (p+1 <= tp.r) hp.push((query){tp.i, p+1, tp.r});
  59. }
  60. cout << ans << endl;
  61. return 0;
  62. }

bzoj3211: 花神游历各国

非负!=正..
如果早做了这题大概就会做出省选相逢是问候了吧...

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. int fa[MAXN];
  5. inline int findf(int nd)
  6. { return fa[nd]!=nd?fa[nd] = findf(fa[nd]):nd; }
  7. inline int lowbit(int i) { return i&(-i); }
  8. long long c[MAXN], dat[MAXN];
  9. int n, m;
  10. void modify(int nd, int dt)
  11. { for (int i = nd; i <= n; i += lowbit(i)) c[i] += dt; }
  12. long long sum(int nd)
  13. { long long ans = 0; for (int i = nd; i; i -= lowbit(i)) ans += c[i]; return ans; }
  14. long long query(int l, int r)
  15. { return sum(r)-sum(l-1); }
  16. inline int read()
  17. {
  18. int a = 0, c;
  19. do c = getchar(); while (!isdigit(c));
  20. while (isdigit(c)) {
  21. a = a*10+c-'0';
  22. c = getchar();
  23. }
  24. return a;
  25. }
  26. int main()
  27. {
  28. scanf("%d", &n);
  29. for (register int i = 1; i <= n; i++) c[i] = read(), dat[i] = c[i], fa[i] = i;
  30. for (register int i = 1; i <= n; i++) if (i+lowbit(i)<=n) c[i+lowbit(i)] += c[i];
  31. fa[n+1] = n+1;
  32. scanf("%d", &m);
  33. for (register int i = 1; i <= m; i++) {
  34. int opt, l, r, d;
  35. opt = read(), l = read(), r = read();
  36. if (opt == 1) printf("%lld\n", query(l, r));
  37. else {
  38. while (l <= r) {
  39. d = dat[l];
  40. d = (int)(sqrt(d))-d;
  41. modify(l, d), dat[l] += d;
  42. if (dat[l] <= 1) fa[l] = l+1;
  43. l = findf(l+1);
  44. }
  45. }
  46. }
  47. return 0;
  48. }

线段树

bzoj4592: [Shoi2015]脑洞治疗仪

比较关键的是完成治疗。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 200005;
  4. int dat[MAXN*4], lc[MAXN*4], rc[MAXN*4], l[MAXN*4], r[MAXN*4];
  5. int change[MAXN*4], llen[MAXN*4], rlen[MAXN*4], len[MAXN*4], top = 0, root = 0;
  6. inline int new_node(int opl, int opr)
  7. { return ++top, l[top] = opl, r[top] = opr, top; }
  8. inline void pdw(int nd) // 1 nh / -1 hole
  9. {
  10. if (!change[nd]) return;
  11. change[lc[nd]] = change[rc[nd]] = change[nd]*(lc[nd]!=0);
  12. dat[nd] = (r[nd]-l[nd]+1)*(change[nd]==1);
  13. llen[nd] = rlen[nd] = len[nd] = (r[nd]-l[nd]+1)*(change[nd]==-1);
  14. change[nd] = 0;
  15. }
  16. inline void update(int nd)
  17. {
  18. pdw(nd), pdw(lc[nd]), pdw(rc[nd]);
  19. if (l[nd] == r[nd]) {
  20. llen[nd] = rlen[nd] = len[nd] = (dat[nd]==0);
  21. return;
  22. }
  23. llen[nd] = llen[lc[nd]]+(dat[lc[nd]] == 0)*llen[rc[nd]];
  24. rlen[nd] = rlen[rc[nd]]+(dat[rc[nd]] == 0)*rlen[lc[nd]];
  25. len[nd] = max(max(len[lc[nd]], len[rc[nd]]), rlen[lc[nd]]+llen[rc[nd]]);
  26. dat[nd] = dat[lc[nd]]+dat[rc[nd]];
  27. }
  28. int pat[MAXN];
  29. void build(int &nd, int l, int r)
  30. {
  31. nd = new_node(l, r);
  32. if (l == r) dat[nd] = pat[r];
  33. else build(lc[nd], l, (l+r)/2), build(rc[nd], (l+r)/2+1, r);
  34. update(nd);
  35. }
  36. void modify(int nd, int opl, int opr, int alc)
  37. {
  38. if (opl > opr) return;
  39. pdw(nd);
  40. if (opl == l[nd] && opr == r[nd]) change[nd] = alc, pdw(nd);
  41. else {
  42. int mid = (l[nd]+r[nd])/2;
  43. if (opr <= mid) modify(lc[nd], opl, opr, alc);
  44. else if (opl > mid) modify(rc[nd], opl, opr, alc);
  45. else modify(lc[nd], opl, mid, alc), modify(rc[nd], mid+1, opr, alc);
  46. pdw(lc[nd]), pdw(rc[nd]), update(nd);
  47. }
  48. }
  49. int query(int nd, int opl, int opr)
  50. {
  51. pdw(nd);
  52. if (opl == l[nd] && opr == r[nd]) return len[nd];
  53. else {
  54. int mid = (l[nd]+r[nd])/2;
  55. pdw(lc[nd]), pdw(rc[nd]);
  56. if (opr <= mid) return query(lc[nd], opl, opr);
  57. else if (opl > mid) return query(rc[nd], opl, opr);
  58. else return max(max(query(lc[nd], opl, mid), query(rc[nd], mid+1, opr)),
  59. min(rlen[lc[nd]], mid-opl+1)+min(llen[rc[nd]], opr-mid));
  60. }
  61. }
  62. void dfs(int nd, int tab = 0)
  63. {
  64. if (!nd) return;
  65. for (int i = 1; i <= tab; i++) putchar(' ');
  66. printf("[%d, %d], dat = %d, llen = %d, rlen = %d, len = %d, change = %d\n", l[nd], r[nd], dat[nd], llen[nd], rlen[nd], len[nd], change[nd]);
  67. dfs(lc[nd], tab+2), dfs(rc[nd], tab+2);
  68. }
  69. int query_sum(int nd, int opl, int opr)
  70. {
  71. if (opl > opr) return 0;
  72. pdw(nd);
  73. int mid = (l[nd]+r[nd])/2;
  74. if (opl == l[nd] && opr == r[nd]) return dat[nd];
  75. else return query_sum(lc[nd], opl, min(opr, mid))+query_sum(rc[nd], max(opl, mid+1), opr);
  76. }
  77. int last_pos(int nd, int k) // in node nd, the first place to have k holes
  78. {
  79. if (l[nd] == r[nd]) return l[nd];
  80. pdw(nd), pdw(lc[nd]), pdw(rc[nd]);
  81. int lp = r[lc[nd]]-l[lc[nd]]+1-dat[lc[nd]];
  82. if (lp >= k) return last_pos(lc[nd], k);
  83. else return last_pos(rc[nd], k-lp);
  84. }
  85. void fix(int ll, int lr, int nl, int nr)
  86. {
  87. int dt = query_sum(root, ll, lr);
  88. modify(root, ll, lr, -1);
  89. if (dt == 0) return;
  90. int k = last_pos(root, nl-1-query_sum(root, 1, nl-1)+dt);
  91. modify(root, nl, min(nr, k), 1);
  92. }
  93. inline int read()
  94. {
  95. int a = 0, c;
  96. do c = getchar(); while (!isdigit(c));
  97. while (isdigit(c))
  98. a = a*10+c-'0', c = getchar();
  99. return a;
  100. }
  101. int n, m;
  102. int main()
  103. {
  104. n = read(), m = read();
  105. for (int i = 1; i <= n; i++) pat[i] = 1;
  106. build(root, 1, n);
  107. for (int i = 1; i <= m; i++) {
  108. int tp, l, r, u, v;
  109. tp = read();
  110. if (tp == 0) l = read(), r = read(), modify(root, l, r, -1);
  111. else if (tp == 1) l = read(), r = read(), u = read(), v = read(), fix(l, r, u, v);
  112. else l = read(), r = read(), printf("%d\n", query(root, l, r));
  113. }
  114. return 0;
  115. }

bzoj2212: [Poi2011]Tree Rotations

线段树合并小技巧。
貌似空间是的?

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 400005;
  4. struct node {
  5. int l, r, lc, rc, dat;
  6. } tree[MAXN*4];
  7. int top = 0, root = 0;
  8. long long c1, c2;
  9. int build(int l, int r, int pos)
  10. {
  11. if (l == r) return tree[++top] = (node){l, r, 0, 0, 1}, top;
  12. int mid = (l+r)>>1, nd = ++top;
  13. tree[nd] = (node){l, r, 0, 0, 1};
  14. if (pos <= mid) return tree[nd].lc = build(l, mid, pos), nd;
  15. else return tree[nd].rc = build(mid+1, r, pos), nd;
  16. }
  17. int merge(int a, int b)
  18. {
  19. if (a == 0 || b == 0) return a+b;
  20. // cerr << "Merging " << a << " " << b << endl;
  21. // display(a, 0), display(b, 0);
  22. c1 += (long long)tree[tree[a].lc].dat*tree[tree[b].rc].dat;
  23. c2 += (long long)tree[tree[b].lc].dat*tree[tree[a].rc].dat;
  24. tree[a].dat += tree[b].dat;
  25. tree[a].lc = merge(tree[a].lc, tree[b].lc);
  26. tree[a].rc = merge(tree[a].rc, tree[b].rc);
  27. return a;
  28. }
  29. int n;
  30. long long cnt = 0, cp = 0;
  31. int dfs()
  32. {
  33. int nd; scanf("%d", &nd);
  34. if (nd != 0) return build(1, n, nd);
  35. ++cp;
  36. int t = cp;
  37. int x = dfs(), y = dfs();
  38. c1 = c2 = 0;
  39. int ret = merge(x, y);
  40. cnt += min(c1, c2);
  41. return ret;
  42. }
  43. int main()
  44. {
  45. scanf("%d", &n);
  46. dfs();
  47. printf("%lld\n", cnt);
  48. return 0;
  49. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注