CodeForces 915E Physical Education Lessons 线段树动态开点

秒速五厘米 2023-07-24 02:28 48阅读 0赞

题目链接:https://codeforces.com/problemset/problem/915/E
题意:q次操作,每次将一段区间置0或者置1,然后输出1~n中0的个数
思路:由于n太大,所以我们考虑线段树动态开点,可以大大减少点的数量便于维护,这也是一道动态开点的模板题

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. #define fi first
  5. #define se second
  6. #define ls rt << 1
  7. #define rs rt << 1|1
  8. #define po pop_back
  9. #define pb push_back
  10. #define mk make_pair
  11. #define lson l, mid, ls
  12. #define rson mid + 1, r, rs
  13. #define pll pair<ll, ll>
  14. #define pii pair<int, int>
  15. #define ull unsigned long long
  16. #define pdd pair<double, double>
  17. const int mod = 1e9 + 7;
  18. const int maxn = 3e5 + 10;
  19. const int inf = 0x3f3f3f3f;
  20. const ll linf = 0x3f3f3f3f3f3f3f3f;
  21. struct seg
  22. {
  23. int lc, rc, val, lazy;
  24. }tree[maxn * 50];
  25. int root = 0, tot = 0; //根结点和结点编号,多样例初始化
  26. int build()
  27. {
  28. ++tot;
  29. tree[tot].lc = tree[tot].rc = tree[tot].val = 0;
  30. tree[tot].lazy = -1; //
  31. return tot;
  32. }
  33. void push_up(int rt)
  34. {
  35. tree[rt].val = tree[tree[rt].lc].val + tree[tree[rt].rc].val;
  36. }
  37. void push_down(int l, int r, int rt)
  38. {
  39. if(tree[rt].lazy != -1 && l != r)
  40. {
  41. int mid = (l + r) >> 1;
  42. if(!tree[rt].lc) tree[rt].lc = build();
  43. if(!tree[rt].rc) tree[rt].rc = build();
  44. tree[tree[rt].lc].val = tree[rt].lazy * (mid - l + 1);
  45. tree[tree[rt].lc].lazy = tree[rt].lazy;
  46. tree[tree[rt].rc].val = tree[rt].lazy * (r - mid);
  47. tree[tree[rt].rc].lazy = tree[rt].lazy;
  48. tree[rt].lazy = -1;
  49. }
  50. }
  51. void update(int ql, int qr, int val, int l, int r, int &rt) //区间修改 传递引用
  52. {
  53. if(!rt) rt = build();
  54. if(ql <= l && r <= qr)
  55. {
  56. tree[rt].val = val * (r - l + 1);
  57. tree[rt].lazy = val;
  58. return;
  59. }
  60. int mid = (l + r) >> 1;
  61. push_down(l, r, rt);
  62. if(ql <= mid) update(ql, qr, val, l, mid, tree[rt].lc);
  63. if(qr > mid) update(ql, qr, val, mid + 1, r, tree[rt].rc);
  64. push_up(rt);
  65. }
  66. int query(int ql, int qr, int l, int r, int rt)
  67. {
  68. if(!rt) return 0;
  69. if(ql <= l && qr <= r)
  70. return tree[rt].val;
  71. int mid = (l + r) >> 1, res = 0;
  72. if(ql <= mid)
  73. res += query(ql, qr, l, mid, tree[rt].lc);
  74. if(qr > mid)
  75. res += query(ql, qr, mid + 1, r, tree[rt].rc);
  76. return res;
  77. }
  78. int main()
  79. {
  80. int n, q;
  81. scanf("%d%d", &n, &q);
  82. while(q--)
  83. {
  84. int l, r, k;
  85. scanf("%d%d%d", &l, &r, &k);
  86. update(l, r, k % 2, 1, n, root);
  87. printf("%d\n", n - query(1, n, 1, n, root));
  88. }
  89. return 0;
  90. }

发表评论

表情:
评论列表 (有 0 条评论,48人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Codeforces 750E 线段DP

    题意:给你一个字符串,有两种操作:1:把某个位置的字符改变。2:询问l到r的子串最少需要删除多少个字符,使得这个子串含有2017子序列,并且没有2016子序列? 思路:线段树