可爱的菜菜子

题目链接https://cometoj.com/contest/38/problem/D?problem_id=1543

数据范围:略。


题解

首先,如果第一个操作是单点修改,我们就只需要用线段树维护区间线性基即可。

但是,第一个操作是区间异或,这就很难受了。

区间操作可以怎么转化成单点?差分呗。

将原序列异或差分之后,确实修改变成了单点修改。

查询是否有影响?其实是没有影响的因为相当于整个一个区间的每个数异或上同一个数(前$l - 1$个数的异或和),线性基不受影响。

代码

  1. #include<bits/stdc++.h>
  2. #define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
  3. #define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
  4. #define lowbit(x) ((x)&-(x))
  5. #define pb push_back
  6. #define fi first
  7. #define se second
  8. #define debug(...) fprintf(stderr,__VA_ARGS__)
  9. #define lowbit(x) ((x)&-(x))
  10. #define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
  11. #define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--)
  12.  
  13. using namespace std;
  14. typedef unsigned long long ull;
  15. typedef long long ll;
  16. typedef pair<int,int> pi;
  17. typedef double db;
  18. typedef long double ldb;
  19.  
  20. namespace io{
  21. const int L=(1<<21)+1;
  22. char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
  23. #ifdef FREOPEN
  24. #define gc() getchar()
  25. #else
  26. #define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
  27. #endif
  28. inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
  29. inline void putc(char x){*oS++=x;if(oS==oT)flush();}
  30. template<class I>
  31. inline void gi(I&x){
  32. for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
  33. for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
  34. }
  35. template<class I>
  36. inline void print(I x){
  37. if(!x)putc('0');if(x<0)putc('-'),x=-x;
  38. while(x)st[++tp]=x%10+'0',x/=10;
  39. while(tp)putc(st[tp--]);
  40. }
  41. inline void gs(char*s,int&l){
  42. for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
  43. for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
  44. }
  45. };
  46. using io::putc;
  47. using io::gi;
  48. using io::gs;
  49. using io::print;
  50.  
  51. const int N=200005,M=32,L=525005;
  52.  
  53. int n,q,a[N],mx;
  54. struct LinearBase{
  55. int a[M],m;
  56. int find(int k){
  57. for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
  58. return k;
  59. }
  60. int query(int x) {
  61. for(int i = 1; i <= m; ++i) if((x^a[i])>x)
  62. x ^= a[i];
  63. return x;
  64. }
  65.  
  66. void ext(int k){
  67. if(mx>>m){
  68. if(k=find(k)){
  69. int j=1;
  70. while(k<=a[j])j++;
  71. ++m;for(int i=m;i>j;i--)a[i]=a[i-1];
  72. a[j]=k;
  73. for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
  74. }
  75. }
  76. }
  77. friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
  78. if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
  79. LinearBase ret=a;
  80. for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
  81. return ret;
  82. }
  83. void clear(){while(m)a[m--]=0;}
  84. }seg[L],ans;
  85.  
  86. void build(int x,int l,int r){
  87. if(l==r){
  88. seg[x].ext(a[l]);
  89. return;
  90. }
  91. int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
  92. build(ls,l,mid);build(rs,mid+1,r);
  93. seg[x]=seg[ls]+seg[rs];
  94. }
  95.  
  96. void modify(int x,int l,int r,int p,int k){
  97. if(l==r){
  98. seg[x].a[1]^=k;
  99. mx=max(mx,seg[x].a[1]);
  100. if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
  101. return;
  102. }
  103. int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
  104. if(p<=mid)modify(ls,l,mid,p,k);
  105. else modify(rs,mid+1,r,p,k);
  106. seg[x]=seg[ls]+seg[rs];
  107. }
  108. void modify(int x,int l,int r,int p,int q,int k){
  109. if(l==r){
  110. seg[x].a[1]^=k;
  111. mx=max(mx,seg[x].a[1]);
  112. if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
  113. return;
  114. }
  115. int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
  116. if(q<=mid)modify(ls,l,mid,p,q,k);
  117. else if(p>mid)modify(rs,mid+1,r,p,q,k);
  118. else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
  119. seg[x]=seg[ls]+seg[rs];
  120. }
  121.  
  122. LinearBase query(int x,int l,int r,int s,int t){
  123. if(l==s&&r==t)return seg[x];
  124. int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
  125. if(t<=mid)return query(ls,l,mid,s,t);
  126. if(s>mid)return query(rs,mid+1,r,s,t);
  127. if(t-mid>=mid-s+1){
  128. LinearBase w=query(rs,mid+1,r,mid+1,t);
  129. if((1ll<<w.m)>mx)return w;
  130. return w+query(ls,l,mid,s,mid);
  131. }
  132. LinearBase w=query(ls,l,mid,s,mid);
  133. if((1ll<<w.m)>mx)return w;
  134. return w+query(rs,mid+1,r,mid+1,t);
  135. }
  136.  
  137. int sum[N];
  138. void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
  139. int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;}
  140.  
  141. int main(){
  142. scanf("%d%d", &n, &q);
  143. for(int i=1,s=0;i<=n;i++) {
  144. scanf("%d", a + i);
  145. add(i, a[i]);
  146. add(i + 1, a[i]);
  147. }
  148. for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
  149. build(1,1,n);
  150. for(int i=1,op,l,r,k;i<=q;i++){
  151. scanf("%d%d%d%d", &op, &l, &r, &k);
  152. if(op==1){
  153. if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
  154. add(l,k);add(r+1,k);
  155. }else{
  156. if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
  157. ans.ext(ask(l));
  158. printf("%d\n", ans.query(k));
  159. }
  160. }
  161. return 0;
  162. }

[Cometoj#3 D]可爱的菜菜子_线段树_差分_线性基的更多相关文章

  1. Comet OJ - Contest #3 D可爱的菜菜子(线段树+线性基的合并)

    这题其实挺经典的,看到求异或最大,显然想到的是线性基,不过这怎么维护?当然区间有关的东西都可以上线段树,区间修改时记录每个点的修改量k,然后合并线性基时再加入线性基.因为线性基是求一组极大线性无关组, ...

  2. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  3. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  4. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  5. BZOJ_2124_等差子序列_线段树+Hash

    BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...

  6. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

  7. BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树

    BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树 Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数 ...

  8. BZOJ_1798_[AHOI2009]维护序列_线段树

    BZOJ_1798_[AHOI2009]维护序列_线段树 题意:老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: ( ...

  9. BZOJ_3307_雨天的尾巴_线段树合并+树上差分

    BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...

随机推荐

  1. MAC 下视频转换格式软件 之 handbrake

    下载地址: https://handbrake.fr/

  2. python ros 设置机器人的位置

    #!/usr/bin/env python import rospy import math from tf import transformations from geometry_msgs.msg ...

  3. Java 使用线程池分批插入或者更新数据

    需求:在开发业务报表时,需要从MySQL数据库读取数据后进行操作,然后写入数据库,使用定时任务跑批. 分析:①兼顾性能,②  MySQL没有Oracle那么方便.强大的存储过程.综上所述,使用线程池以 ...

  4. cesium billboard跨域问题1

    群里小伙伴问道使用billboard加载图片时出现跨域问题,一般认为在服务器端设置 Access-Control-Allow-Origin: * 例如用tomcat发布图片服务,可以这样设置:http ...

  5. python中的匿名函数

    python 使用 lambda 来创建匿名函数. 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数. lambda 只是一个表达式,函数体比 def 简单很多. lambda的主体是一 ...

  6. elasticsearch _bulk api

    https://www.elastic.co/guide/cn/elasticsearch/guide/current/bulk.htmlbulk API 允许在单个步骤中进行多次 create . ...

  7. jenkins权限问题

    今天用jenkins的时候,构建失败,看了下控制台输出,提示是缺少权限,以前也遇到过这个问题,当时是通过把相关文件夹权限设置为777解决的,这种办法有两个不好的地方,一是这样一来任何用户都能操作这个文 ...

  8. 通过.zip安装eclipse插件

    参考地址https://stackoverflow.com/questions/5482554/how-to-install-plugin-for-eclipse-from-zip

  9. 攻防世界RE1 writeup

    解题过程 将题目给出的exe文件拖入ida中,查看main函数. 分析函数的逻辑,发现用户需要输出一个字符串,存储到变量v9中.如果v9的值与v5的值相等则会打印unk_413e90中的值,否则打印a ...

  10. idea内存不足或过大闪退

    昨天在码云找了个开源后台项目https://gitee.com/shuzheng/zheng,各种修改后终于跑起来了, 运行没多久就提示内存不足,安装目录配置虚拟机最大可用内存为512M idea弹窗 ...