[关闭]
@xiaoziyao 2020-10-25T11:49:54.000000Z 字数 1871 阅读 917

CF1100F Ivan and Burgers解题报告

解题报告


CF1100F Ivan and Burgers解题报告:

更好的阅读体验

题意

分析

这道题的测试点数是真的多。。。

一道猫树分治+线性基题。

猫树分治的操作:从区间中选一个分治中点,预处理的信息,预处理的信息,然后对所有跨越了的询问快速合并,不经过直接向子区间分治。

这道题我们可以直接把询问离线,然后上猫树分治。

具体地,我们用的暴力预处理的线性基(其中),然后在合并的时候用的暴力合并跨越的两个线性基。

总复杂度:

代码

  1. #include<stdio.h>
  2. const int maxn=500005,maxm=500005,maxk=31;
  3. int n,m;
  4. int a[maxn],ans[maxm];
  5. struct question{//询问
  6. int l,r,id;
  7. }q[maxm],tmp1[maxm],tmp2[maxm];
  8. struct base{//线性基
  9. int p[maxk];
  10. void clear(){
  11. for(int i=0;i<maxk;i++)
  12. p[i]=0;
  13. }
  14. }b[maxn];
  15. void insert(base &now,int x){//线性基插入
  16. for(int i=30;i>=0;i--){
  17. if(((x>>i)&1)==0)
  18. continue;
  19. if(now.p[i]==0){
  20. now.p[i]=x;
  21. return ;
  22. }
  23. x^=now.p[i];
  24. }
  25. }
  26. base merge(base a,base b){//线性基合并
  27. for(int i=0;i<=30;i++)
  28. if(b.p[i])
  29. insert(a,b.p[i]);
  30. return a;
  31. }
  32. int getmax(base x){//线性基求异或最大值
  33. int res=0;
  34. for(int i=30;i>=0;i--)
  35. if((res^x.p[i])>res)
  36. res^=x.p[i];
  37. return res;
  38. }
  39. void solve(int l,int r,int ql,int qr){//猫树分治
  40. if(ql>qr)
  41. return ;
  42. if(l==r){
  43. for(int i=ql;i<=qr;i++)
  44. ans[q[i].id]=a[l];
  45. return ;
  46. }
  47. int mid=(l+r)>>1,cnt1=0,cnt2=0;
  48. b[mid].clear(),insert(b[mid],a[mid]);
  49. for(int i=mid-1;i>=l;i--)
  50. b[i]=b[i+1],insert(b[i],a[i]);
  51. for(int i=mid+1;i<=r;i++)
  52. b[i]=b[i-1],insert(b[i],a[i]);
  53. for(int i=ql;i<=qr;i++){//合并左右预处理过的线性基
  54. if(l<=q[i].l&&q[i].l<=mid&&mid+1<=q[i].r&&q[i].r<=r){
  55. ans[q[i].id]=getmax(merge(b[q[i].l],b[q[i].r]));
  56. continue;
  57. }
  58. if(q[i].l<=mid&&q[i].r<=mid)
  59. tmp1[++cnt1]=q[i];
  60. else tmp2[++cnt2]=q[i];
  61. }
  62. for(int i=1;i<=cnt1;i++)
  63. q[ql+i-1]=tmp1[i];
  64. for(int i=1;i<=cnt2;i++)
  65. q[ql+cnt1+i-1]=tmp2[i];
  66. solve(l,mid,ql,ql+cnt1-1),solve(mid+1,r,ql+cnt1,ql+cnt1+cnt2-1);//分治解决子问题
  67. }
  68. int main(){
  69. scanf("%d",&n);
  70. for(int i=1;i<=n;i++)
  71. scanf("%d",&a[i]);
  72. scanf("%d",&m);
  73. for(int i=1;i<=m;i++){
  74. scanf("%d%d",&q[i].l,&q[i].r);
  75. q[i].id=i;
  76. }
  77. solve(1,n,1,m);
  78. for(int i=1;i<=m;i++)
  79. printf("%d\n",ans[i]);
  80. return 0;
  81. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注