• 练习41,[SCOI2010] 序列操作【线段树】


    P2572 [SCOI2010] 序列操作 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    思路不是很难,码量很大,调试难度高,一个bug找一天(bushi

    稍微难一些的就是求[l,r] 区间内最多有多少个连续的 1,可以分别维护一段区间左端,中间,右端有多少个连续的1和0来实现。同时要注意的点是赋0和赋1标记可以覆盖取反标记,而取反标记不能覆盖赋0和赋1标记,而且取反标记更改时要^=1

    具体看代码注释

    1. #include
    2. using namespace std;
    3. #define INF 0x3f3f3f3f
    4. #define INF_L 0x3f3f3f3f3f3f3f3fLL
    5. #define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
    6. #define endl '\n'
    7. #define T int TT;cin >> TT;while (TT--)
    8. #define lint long long
    9. #define PII pair
    10. #define PLL pair
    11. #define pb push_back
    12. #define eb emplace_back
    13. int a[100010];
    14. int n,m;
    15. struct node{
    16. int l,r,sum;
    17. int sw,t0,t1; //sw取反标记,t0赋0标记,t1赋1标记
    18. int ll1,lm1,lr1,ll0,lm0,lr0;
    19. //ll1维护区间左端连续1的长度
    20. //lm1维护区间中间最长连续1的长度
    21. //lr1维护区间右端连续1的长度
    22. }tree[400010],node0;
    23. void pushup(int p){
    24. tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
    25. tree[p].ll1=tree[p<<1].ll1;
    26. tree[p].lr1=tree[p<<1|1].lr1;
    27. /*如果左或右端的连续1长度等于区间长度,则需要将另一段要合并的区间的左端或右端
    28. 的连续1长度加上*/
    29. if(tree[p<<1].ll1==tree[p<<1].r-tree[p<<1].l+1){
    30. tree[p].ll1+=tree[p<<1|1].ll1;
    31. }
    32. if(tree[p<<1|1].lr1==tree[p<<1|1].r-tree[p<<1|1].l+1){
    33. tree[p].lr1+=tree[p<<1].lr1;
    34. }
    35. tree[p].lm1=max(tree[p<<1].lr1+tree[p<<1|1].ll1,max(tree[p<<1].lm1,tree[p<<1|1].lm1));
    36. tree[p].ll0=tree[p<<1].ll0;
    37. tree[p].lr0=tree[p<<1|1].lr0;
    38. if(tree[p<<1].ll0==tree[p<<1].r-tree[p<<1].l+1){
    39. tree[p].ll0+=tree[p<<1|1].ll0;
    40. }
    41. if(tree[p<<1|1].lr0==tree[p<<1|1].r-tree[p<<1|1].l+1){
    42. tree[p].lr0+=tree[p<<1].lr0;
    43. }
    44. tree[p].lm0=max(tree[p<<1].lr0+tree[p<<1|1].ll0,max(tree[p<<1].lm0,tree[p<<1|1].lm0));
    45. }
    46. void pushdown(int p){
    47. if(tree[p].t0){
    48. tree[p<<1].t0=tree[p<<1|1].t0=1;
    49. tree[p<<1].t1=tree[p<<1|1].t1=0;
    50. tree[p<<1].sw=tree[p<<1|1].sw=0;
    51. tree[p<<1].sum=0;
    52. tree[p<<1].ll1=tree[p<<1].lm1=tree[p<<1].lr1=0;
    53. tree[p<<1].ll0=tree[p<<1].lm0=tree[p<<1].lr0=tree[p<<1].r-tree[p<<1].l+1;
    54. tree[p<<1|1].sum=0;
    55. tree[p<<1|1].ll1=tree[p<<1|1].lm1=tree[p<<1|1].lr1=0;
    56. tree[p<<1|1].ll0=tree[p<<1|1].lm0=tree[p<<1|1].lr0=tree[p<<1|1].r-tree[p<<1|1].l+1;
    57. }
    58. if(tree[p].t1){
    59. tree[p<<1].t0=tree[p<<1|1].t0=0;
    60. tree[p<<1].t1=tree[p<<1|1].t1=1;
    61. tree[p<<1].sw=tree[p<<1|1].sw=0;
    62. tree[p<<1].sum=tree[p<<1].r-tree[p<<1].l+1;
    63. tree[p<<1].ll1=tree[p<<1].lm1=tree[p<<1].lr1=tree[p<<1].r-tree[p<<1].l+1;
    64. tree[p<<1].ll0=tree[p<<1].lm0=tree[p<<1].lr0=0;
    65. tree[p<<1|1].sum=tree[p<<1|1].r-tree[p<<1|1].l+1;
    66. tree[p<<1|1].ll1=tree[p<<1|1].lm1=tree[p<<1|1].lr1=tree[p<<1|1].r-tree[p<<1|1].l+1;
    67. tree[p<<1|1].ll0=tree[p<<1|1].lm0=tree[p<<1|1].lr0=0;
    68. }
    69. if(tree[p].sw){
    70. tree[p<<1].sw^=1;
    71. tree[p<<1|1].sw^=1;
    72. tree[p<<1].sum=tree[p<<1].r-tree[p<<1].l+1-tree[p<<1].sum;
    73. swap(tree[p<<1].ll1,tree[p<<1].ll0);
    74. swap(tree[p<<1].lm1,tree[p<<1].lm0);
    75. swap(tree[p<<1].lr1,tree[p<<1].lr0);
    76. tree[p<<1|1].sum=tree[p<<1|1].r-tree[p<<1|1].l+1-tree[p<<1|1].sum;
    77. swap(tree[p<<1|1].ll1,tree[p<<1|1].ll0);
    78. swap(tree[p<<1|1].lm1,tree[p<<1|1].lm0);
    79. swap(tree[p<<1|1].lr1,tree[p<<1|1].lr0);
    80. }
    81. tree[p].t0=tree[p].t1=tree[p].sw=0;
    82. }
    83. void build(int l,int r,int p=1){
    84. tree[p].l=l,tree[p].r=r;
    85. tree[p].ll1=tree[p].lm1=tree[p].lr1=tree[p].ll0=tree[p].lm0=tree[p].lr0=0;
    86. tree[p].sw=tree[p].t0=tree[p].t1=0;
    87. if(l==r){
    88. tree[p].sum=a[l];
    89. if(a[l]) tree[p].ll1=tree[p].lm1=tree[p].lr1=1;
    90. else tree[p].ll0=tree[p].lm0=tree[p].lr0=1;
    91. return ;
    92. }
    93. int mid=l+r>>1;
    94. build(l,mid,p<<1);
    95. build(mid+1,r,p<<1|1);
    96. pushup(p);
    97. }
    98. void turn(int l,int r,int t,int p=1){ //赋值
    99. if(l<=tree[p].l && r>=tree[p].r){
    100. if(t==0){
    101. tree[p].t0=1,tree[p].t1=0;
    102. tree[p].sum=0;
    103. tree[p].ll1=tree[p].lm1=tree[p].lr1=0;
    104. tree[p].ll0=tree[p].lm0=tree[p].lr0=tree[p].r-tree[p].l+1;
    105. }
    106. else {
    107. tree[p].t0=0,tree[p].t1=1;
    108. tree[p].sum=tree[p].r-tree[p].l+1;
    109. tree[p].ll1=tree[p].lm1=tree[p].lr1=tree[p].r-tree[p].l+1;
    110. tree[p].ll0=tree[p].lm0=tree[p].lr0=0;
    111. }
    112. tree[p].sw=0;
    113. return ;
    114. }
    115. pushdown(p);
    116. int mid=tree[p].l+tree[p].r>>1;
    117. if(l<=mid) turn(l,r,t,p<<1);
    118. if(r>mid) turn(l,r,t,p<<1|1);
    119. pushup(p);
    120. }
    121. void swc(int l,int r,int p=1){ //取反
    122. if(l<=tree[p].l && r>=tree[p].r){
    123. tree[p].sum=tree[p].r-tree[p].l+1-tree[p].sum;
    124. swap(tree[p].ll1,tree[p].ll0);
    125. swap(tree[p].lm1,tree[p].lm0);
    126. swap(tree[p].lr1,tree[p].lr0);
    127. tree[p].sw^=1;
    128. return ;
    129. }
    130. pushdown(p);
    131. int mid=tree[p].l+tree[p].r>>1;
    132. if(l<=mid) swc(l,r,p<<1);
    133. if(r>mid) swc(l,r,p<<1|1);
    134. pushup(p);
    135. }
    136. int querysum(int l,int r,int p=1){ //询问区间1个数
    137. if(l<=tree[p].l && r>=tree[p].r) return tree[p].sum;
    138. pushdown(p);
    139. int mid=tree[p].l+tree[p].r>>1,sum=0;
    140. if(l<=mid) sum+=querysum(l,r,p<<1);
    141. if(r>mid) sum+=querysum(l,r,p<<1|1);
    142. return sum;
    143. }
    144. node queryl(int l,int r,int p=1){ //询问区间最长连续1
    145. if(l<=tree[p].l && r>=tree[p].r) return tree[p];
    146. pushdown(p);
    147. int mid=tree[p].l+tree[p].r>>1;
    148. node x=node0,lx=node0,rx=node0;
    149. int fl=0,fr=0;
    150. if(l<=mid){lx=queryl(l,r,p<<1); fl=1;}
    151. if(r>mid){rx=queryl(l,r,p<<1|1); fr=1;}
    152. if(fl+fr==2){
    153. x.ll1=lx.ll1;
    154. x.lr1=rx.lr1;
    155. if(lx.ll1==lx.r-lx.l+1){
    156. x.ll1+=rx.ll1;
    157. }
    158. if(rx.lr1==rx.r-rx.l+1){
    159. x.lr1+=lx.lr1;
    160. }
    161. x.lm1=max(lx.lr1+rx.ll1,max(lx.lm1,rx.lm1));
    162. }
    163. else if(fl==0) x=rx;
    164. else if(fr==0) x=lx;
    165. return x;
    166. }
    167. void init(){
    168. node0.ll1=node0.lm1=node0.lr1=node0.ll0=node0.lm0=node0.lr0=0;
    169. node0.sw=node0.t0=node0.t1=0;
    170. }
    171. int main(){
    172. NOTLE;
    173. init();
    174. cin >> n >> m;
    175. for(int i=1;i<=n;i++) cin >> a[i];
    176. build(1,n);
    177. for(int i=1;i<=m;i++){
    178. int opt,l,r;
    179. cin >> opt >> l >> r;
    180. l++,r++;
    181. if(opt==0){
    182. turn(l,r,0);
    183. }
    184. if(opt==1){
    185. turn(l,r,1);
    186. }
    187. if(opt==2){
    188. swc(l,r);
    189. }
    190. if(opt==3){
    191. cout << querysum(l,r) << endl;
    192. }
    193. if(opt==4){
    194. node x=queryl(l,r);
    195. cout << max(max(x.ll1,x.lr1),x.lm1) << endl;
    196. }
    197. }
    198. return 0;
    199. }

    此题还有一种解法是珂朵莉树,但只能过随机的数据,无法通过洛谷上已经针对过的数据

    1. #include
    2. using namespace std;
    3. #define INF 0x3f3f3f3f
    4. #define INF_L 0x3f3f3f3f3f3f3f3fLL
    5. #define NOTLE ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
    6. #define endl '\n'
    7. #define T int TT;cin >> TT;while (TT--)
    8. #define lint long long
    9. #define PII pair
    10. #define PLL pair
    11. #define S_IT set::iterator
    12. #define pb push_back
    13. #define eb emplace_back
    14. #define MAXN 100002
    15. typedef int type;
    16. struct Node{
    17. unsigned int l;
    18. unsigned int r;
    19. mutable type data;
    20. Node(unsigned int a, unsigned int b = 0, type c = 0);
    21. bool operator <(const Node &a) const{return l < a.l;}
    22. };
    23. Node::Node(unsigned int a, unsigned int b, type c){l = a; r = b; data = c;}
    24. set s;
    25. S_IT split(unsigned int pos){
    26. S_IT it = s.lower_bound(Node(pos));
    27. if (it != s.end() && it->l == pos) return it;
    28. --it;
    29. unsigned int l = it->l, r = it->r;
    30. type data = it->data;
    31. s.erase(it);
    32. s.insert(Node(l, pos - 1, data));
    33. return s.insert(Node(pos, r, data)).first;
    34. }
    35. void swc(int l,int r,int val){
    36. S_IT it2 = split(r + 1), it1 = split(l);
    37. s.erase(it1, it2);
    38. s.insert(Node(l, r, val));
    39. return;
    40. }
    41. void rev(int l,int r){
    42. S_IT it2 = split(r + 1), it1 = split(l);
    43. for (; it1 != it2; ++it1)
    44. it1->data ^= 1;
    45. }
    46. int sum(int l,int r){
    47. S_IT it2 = split(r + 1), it1 = split(l);
    48. int res=0;
    49. for (; it1 != it2; ++it1)
    50. if(it1->data) res+=(it1->r)-(it1->l)+1;
    51. return res;
    52. }
    53. int con(int l,int r){
    54. int res=0,temp=0;
    55. S_IT it2 = split(r + 1), it1 = split(l);
    56. for (; it1 != it2; ++it1){
    57. if (it1->data){
    58. temp+=(it1->r)-(it1->l)+1;
    59. }
    60. else{
    61. res=max(res,temp);
    62. temp=0;
    63. }
    64. }
    65. return max(res, temp);
    66. }
    67. int main(){
    68. NOTLE;
    69. int n, m;
    70. cin >> n >> m;
    71. for (int i = 0; i < n; ++i){
    72. int temp;
    73. cin >> temp;
    74. s.insert(Node(i, i, temp));
    75. }
    76. s.insert(Node(n, n, 0));
    77. while(m--){
    78. int op,a,b;
    79. cin >> op >> a >> b;
    80. if (op==0) swc(a, b, 0);
    81. if (op==1) swc(a, b, 1);
    82. if (op==2) rev(a, b);
    83. if (op==3) cout << sum(a, b) << endl;
    84. if (op==4) cout << con(a, b) << endl;
    85. }
    86. return 0;
    87. }

  • 相关阅读:
    volatile的用途和说明
    LeetCode307 周赛(补记)
    SystemVerilog学习-10-验证量化和覆盖率
    RabbitMQ---SpringAMQP的使用,五种消息模型的示例
    一体化伺服电机在三轴钻孔机中的应用
    7.1、如何理解Flink中的时间语义
    界面控件DevExpress WinForms HTML-CSS模板:预设计UI模板加速.NET应用开发
    【优化算法】基于matlab量子粒子群算法求解单目标优化问题【含Matlab源码 2203期】
    ASP.NET Core - 选项系统之源码介绍
    使用css 与 js 两种方式实现导航栏吸顶效果
  • 原文地址:https://blog.csdn.net/ILECY/article/details/126931496