[关闭]
@xiaoziyao 2021-08-14T22:20:32.000000Z 字数 2389 阅读 929

loj#6507. 「雅礼集训 2018 Day7」A 解题报告

解题报告


loj#6507. 「雅礼集训 2018 Day7」A解题报告:

题意

给定一个长为 的序列, 次操作,支持区间或,区间与,区间求最小值。(

分析

线段树+势能分析。

考虑线段树每个结点记录区间的与值 ,或值 ,最小值 ,然后分类讨论。

操作:

操作:

有一个小问题,为什么第二种情况可以这样判,比如如果与操作的时候有某一位 没有,可是这个区间的这一位并不相同,那这样不就有问题吗?但是这种情况这些位置都会变成 。(是不是只有我有这么傻逼的问题)

我们想一想怎么证明复杂度。

如果当前递归到了操作区间内,那么一次操作会产生的影响:让区间若干个不同色位集体变成同色,或者集体某一位异或 ,第二种情况小号的复杂度应该与第一种情况是一致的,第一种情况的复杂度应该是 ,所以复杂度是两个 的。

代码

《15min rush 2k 代码》

  1. #include<stdio.h>
  2. #define lc(x) (x)<<1
  3. #define rc(x) (x)<<1|1
  4. const int maxn=500005,maxt=maxn<<2,inf=2147483647;
  5. int n,m;
  6. int a[maxn],vand[maxt],vor[maxt],minn[maxt],lazy[maxt];
  7. inline int min(int a,int b){
  8. return a<b? a:b;
  9. }
  10. inline void pushup(int now){
  11. vand[now]=vand[lc(now)]&vand[rc(now)];
  12. vor[now]=vor[lc(now)]|vor[rc(now)];
  13. minn[now]=min(minn[lc(now)],minn[rc(now)]);
  14. }
  15. inline void getlazy(int now,int v){
  16. vand[now]=vor[now]=minn[now]=lazy[now]=v;
  17. }
  18. inline void pushdown(int now){
  19. if(lazy[now]!=-1)
  20. getlazy(lc(now),lazy[now]),getlazy(rc(now),lazy[now]),lazy[now]=-1;
  21. }
  22. void build(int l,int r,int now){
  23. lazy[now]=-1;
  24. if(l==r){
  25. getlazy(now,a[l]);
  26. return ;
  27. }
  28. int mid=(l+r)>>1;
  29. build(l,mid,lc(now)),build(mid+1,r,rc(now));
  30. pushup(now);
  31. }
  32. void updateand(int l,int r,int now,int L,int R,int v){
  33. if((vor[now]&v)==vor[now])
  34. return ;
  35. if(L<=l&&r<=R&&(vor[now]&v)==(vand[now]&v)){
  36. getlazy(now,vor[now]&v);
  37. return ;
  38. }
  39. int mid=(l+r)>>1;
  40. pushdown(now);
  41. if(L<=mid)
  42. updateand(l,mid,lc(now),L,R,v);
  43. if(mid<R)
  44. updateand(mid+1,r,rc(now),L,R,v);
  45. pushup(now);
  46. }
  47. void updateor(int l,int r,int now,int L,int R,int v){
  48. if((vand[now]|v)==vand[now])
  49. return ;
  50. if(L<=l&&r<=R&&(vand[now]|v)==(vor[now]|v)){
  51. getlazy(now,vand[now]|v);
  52. return ;
  53. }
  54. int mid=(l+r)>>1;
  55. pushdown(now);
  56. if(L<=mid)
  57. updateor(l,mid,lc(now),L,R,v);
  58. if(mid<R)
  59. updateor(mid+1,r,rc(now),L,R,v);
  60. pushup(now);
  61. }
  62. int query(int l,int r,int now,int L,int R){
  63. if(L<=l&&r<=R)
  64. return minn[now];
  65. int mid=(l+r)>>1,res=inf;
  66. pushdown(now);
  67. if(L<=mid)
  68. res=min(res,query(l,mid,lc(now),L,R));
  69. if(mid<R)
  70. res=min(res,query(mid+1,r,rc(now),L,R));
  71. return res;
  72. }
  73. int main(){
  74. scanf("%d%d",&n,&m);
  75. for(int i=1;i<=n;i++)
  76. scanf("%d",&a[i]);
  77. build(1,n,1);
  78. for(int i=1;i<=m;i++){
  79. int opt,l,r,v;
  80. scanf("%d%d%d",&opt,&l,&r);
  81. if(opt==1){
  82. scanf("%d",&v);
  83. updateand(1,n,1,l,r,v);
  84. }
  85. if(opt==2){
  86. scanf("%d",&v);
  87. updateor(1,n,1,l,r,v);
  88. }
  89. if(opt==3)
  90. printf("%d\n",query(1,n,1,l,r));
  91. }
  92. return 0;
  93. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注