可爱的菜菜子

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

数据范围:略。


题解

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

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

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

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

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

代码

#include<bits/stdc++.h>
#define mms(a,n) memset(a,0,sizeof((a)[0])*(n))
#define mmp(a,b,n) memcpy(a,b,sizeof((b)[0])*(n))
#define lowbit(x) ((x)&-(x))
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) ((x)&-(x))
#define fo(i,l,r) for(register int i=l,_lim_=r;i<=_lim_;i++)
#define fd(i,r,l) for(register int i=r,_lim_=l;i>=_lim_;i--) using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pi;
typedef double db;
typedef long double ldb; namespace io{
const int L=(1<<21)+1;
char ibuf[L],*iS,*iT,obuf[L],*oS=obuf,*oT=obuf+L-1,c,st[55];int f,tp;
#ifdef FREOPEN
#define gc() getchar()
#else
#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,L,stdin),(iS==iT?EOF:*iS++)):*iS++)
#endif
inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
inline void putc(char x){*oS++=x;if(oS==oT)flush();}
template<class I>
inline void gi(I&x){
for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;
}
template<class I>
inline void print(I x){
if(!x)putc('0');if(x<0)putc('-'),x=-x;
while(x)st[++tp]=x%10+'0',x/=10;
while(tp)putc(st[tp--]);
}
inline void gs(char*s,int&l){
for(c=gc();c!='_'&&(c<'a'||c>'z');c=gc());
for(l=0;c=='_'||c<='z'&&c>='a';c=gc())s[l++]=c;
}
};
using io::putc;
using io::gi;
using io::gs;
using io::print; const int N=200005,M=32,L=525005; int n,q,a[N],mx;
struct LinearBase{
int a[M],m;
int find(int k){
for(int i=1;i<=m;i++)if((k^a[i])<k)k^=a[i];
return k;
}
int query(int x) {
for(int i = 1; i <= m; ++i) if((x^a[i])>x)
x ^= a[i];
return x;
} void ext(int k){
if(mx>>m){
if(k=find(k)){
int j=1;
while(k<=a[j])j++;
++m;for(int i=m;i>j;i--)a[i]=a[i-1];
a[j]=k;
for(int i=1;i<j;i++)if((k^a[i])<a[i])a[i]^=k;
}
}
}
friend LinearBase operator+(const LinearBase&a,const LinearBase&b){
if((1ll<<a.m)>mx)return a;if((1ll<<b.m)>mx)return b;
LinearBase ret=a;
for(int i=1;i<=b.m;i++)ret.ext(b.a[i]);
return ret;
}
void clear(){while(m)a[m--]=0;}
}seg[L],ans; void build(int x,int l,int r){
if(l==r){
seg[x].ext(a[l]);
return;
}
int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
build(ls,l,mid);build(rs,mid+1,r);
seg[x]=seg[ls]+seg[rs];
} void modify(int x,int l,int r,int p,int k){
if(l==r){
seg[x].a[1]^=k;
mx=max(mx,seg[x].a[1]);
if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
return;
}
int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
if(p<=mid)modify(ls,l,mid,p,k);
else modify(rs,mid+1,r,p,k);
seg[x]=seg[ls]+seg[rs];
}
void modify(int x,int l,int r,int p,int q,int k){
if(l==r){
seg[x].a[1]^=k;
mx=max(mx,seg[x].a[1]);
if(!seg[x].a[1])seg[x].m=0;else seg[x].m=1;
return;
}
int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
if(q<=mid)modify(ls,l,mid,p,q,k);
else if(p>mid)modify(rs,mid+1,r,p,q,k);
else modify(ls,l,mid,p,k),modify(rs,mid+1,r,q,k);
seg[x]=seg[ls]+seg[rs];
} LinearBase query(int x,int l,int r,int s,int t){
if(l==s&&r==t)return seg[x];
int mid=(l+r)>>1,ls=x<<1,rs=ls|1;
if(t<=mid)return query(ls,l,mid,s,t);
if(s>mid)return query(rs,mid+1,r,s,t);
if(t-mid>=mid-s+1){
LinearBase w=query(rs,mid+1,r,mid+1,t);
if((1ll<<w.m)>mx)return w;
return w+query(ls,l,mid,s,mid);
}
LinearBase w=query(ls,l,mid,s,mid);
if((1ll<<w.m)>mx)return w;
return w+query(rs,mid+1,r,mid+1,t);
} int sum[N];
void add(int x,int u){while(x<=n)sum[x]^=u,x+=lowbit(x);}
int ask(int x){int r=0;while(x)r^=sum[x],x-=lowbit(x);return r;} int main(){
scanf("%d%d", &n, &q);
for(int i=1,s=0;i<=n;i++) {
scanf("%d", a + i);
add(i, a[i]);
add(i + 1, a[i]);
}
for(int i=n;i>=1;i--)mx=max(mx,a[i]^=a[i-1]);
build(1,1,n);
for(int i=1,op,l,r,k;i<=q;i++){
scanf("%d%d%d%d", &op, &l, &r, &k);
if(op==1){
if(r<n)modify(1,1,n,l,r+1,k);else modify(1,1,n,l,k);
add(l,k);add(r+1,k);
}else{
if(l<r)ans=query(1,1,n,l+1,r);else ans.clear();
ans.ext(ask(l));
printf("%d\n", ans.query(k));
}
}
return 0;
}

[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. 007_FreeROTS队列

    (一)目的:进程间的通信 (二)队列创建 1. 动态创建队列,函数 xQueueCreate() QueueHandle_t xQueueCreate( UBaseType_t uxQueueLeng ...

  2. React中生命周期

    1.过时的生命周期(v16.3之前) 1.当前组件初次渲染: 绿色表示执行顺序. constructor(): 如果不需要初始化,可以直接省略,会自动补全该函数. 可以在这个方法中初始化this.st ...

  3. LOJ6436. 「PKUSC2018」神仙的游戏 [NTT]

    传送门 思路 首先通过各种手玩/找规律/严谨证明,发现当\(n-i\)为border当且仅当对于任意\(k\in[0,i)\),模\(i\)余\(k\)的位置没有同时出现0和1. 换句话说,拿出任意一 ...

  4. P1484 种树——数据结构优先队列

    种了一下午的树,终于给搞明白了((多谢各位大神的题解)(题解就不能讲清楚点吗(看不见看不见))): 你有k个树,你可以种在一条直线上,每个位置都有一个价值,如果你把树种在这里就可以获得这个价值,但是条 ...

  5. 2019巅峰极客CTF-web1(LOL英雄联盟)

    今晚有空 以后随缘写博客了 好好沉淀 web1当天做出的队伍很少 其实不难    折腾到最后就差一步  可惜    0x01 读取文件 截图没留了 只留了代码部分. 有个页面  有上传和下载功能 起初 ...

  6. Apache Web服务器 安装步骤 和遇到的坑

    Apache Web服务器是开发放源码的网页服务器,我们看到的网页都是上传到服务器然后呈现给用户的. 在开发中,在自己的电脑上安装Apache Web服务器,你的电脑也会成为服务器,配置文件,访问你的 ...

  7. SQL Server Management Studio 清除用户名和密码

    SQL Server Management Studio 2018 delete the file C:\Users\%username%\AppData\Roaming\Microsoft\SQL  ...

  8. 【转】Mac find 去除 “Permission denied” 信息的方法

    转自 https://segmentfault.com/a/1190000007058875 Mac 下查找文件,最简单的方法应该是 mdfind filename 等同于 mdfind -name ...

  9. IDEA版本控制工具VCS中使用Git,以及快捷键总结(不使用命令)

    场景介绍: 工作中多人使用版本控制软件协作开发,常见的应用场景归纳如下: 假设小组中有两个人,组长小张,组员小袁 场景一:小张创建项目并提交到远程Git仓库 场景二:小袁从远程Git仓库上获取项目源码 ...

  10. [转][echarts]地图轮播

    代码片断: 来自:https://blog.csdn.net/qq_36947128/article/details/90899564 function Play(){ chart.dispatchA ...