[Cometoj#3 D]可爱的菜菜子_线段树_差分_线性基
可爱的菜菜子
题目链接: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]可爱的菜菜子_线段树_差分_线性基的更多相关文章
- Comet OJ - Contest #3 D可爱的菜菜子(线段树+线性基的合并)
这题其实挺经典的,看到求异或最大,显然想到的是线性基,不过这怎么维护?当然区间有关的东西都可以上线段树,区间修改时记录每个点的修改量k,然后合并线性基时再加入线性基.因为线性基是求一组极大线性无关组, ...
- BZOJ_4636_蒟蒻的数列_线段树+动态开点
BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针
BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...
- BZOJ_2124_等差子序列_线段树+Hash
BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...
- BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心
BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...
- BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树
BZOJ_1828_[Usaco2010 Mar]balloc 农场分配_线段树 Description Input 第1行:两个用空格隔开的整数:N和M * 第2行到N+1行:第i+1行表示一个整数 ...
- BZOJ_1798_[AHOI2009]维护序列_线段树
BZOJ_1798_[AHOI2009]维护序列_线段树 题意:老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: ( ...
- BZOJ_3307_雨天的尾巴_线段树合并+树上差分
BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...
随机推荐
- 009_linuxC++之_友元函数
(一)定义:友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数.类授予它的友元特别的访问权.通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数(否则当你想更新你的类时,还要征得其 ...
- springboot项目没错,但就是报红叉
1.报错原因: Description Resource Path Location TypeCannot change version of project facet Dynamic Web Mo ...
- CF922D Robot Vacuum Cleaner 贪心+排序
正确的贪心方法:按照比例排序. code: #include <bits/stdc++.h> #define N 200000 #define ll long long #define s ...
- Django RestFramework (DRF)
准备: 下载 pip install djangorestframework 一 APIView源码解析 1 预备知识 CBV(class based view)FBV(function based ...
- 树莓派中将caplock映射为esc键
据说,喜欢vimer都呵caplock有仇,明明caplock占着原来esc的位置,却从来没有起到应有的作用,你说气人吗,没关系,我改啊:将下面语句加入到.bashrc中,启动即可xmodmap -e ...
- sql注入笔记-sqlite
1. SQLite 1. 常用语句及基本结构 (1)sqlite因为其比较简易每个db文件就是一个数据库,所以不存在information_schema数据库,但存在类似作用的表sqlite_mast ...
- Memcache启动停止
启动Memcached root -P /var/run/memcached.pid 1)启动参数说明: -d 选项是启动一个守护进程, -l 是监听的服务器IP地址,默认为所有网卡. -p 是设置M ...
- Flutter移动电商实战 --(35)列表页_上拉加载更多制作
右侧列表上拉加载配合类别的切换 上拉加载需要一个page参数,当点击大类或者小类的时候,这个page就要变成1 provide内定义参数 首先我们需要定义一个page的变量 下图是我们之前在首页的时候 ...
- Python下划线命名模式
- MySQL 5.7新增加的json数据类型
MySQL 5.7中有json存储类型了以前我们只能通过php来进行序列化了不过现在就不需要了我们可以直接使用MySQL 5.7的json数据类型来存储json格式数据了,具体来看介绍. 在MyS ...