Description
我有一个数列
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an,每个
a
i
a_i
ai 都是小于
2
m
2^m
2m 的非负整数。
现在请您实现三种操作,格式说明如下:
1
x
y
w
1\ x\ y\ w
1 x y w:对于所有
x
≤
i
≤
y
x≤i≤y
x≤i≤y,将
a
i
ai
ai 修改为
a
i
x
o
r
w
a_i\ xor\ w
ai xor w。其中
w
w
w 是一个小于
2
m
2^m
2m 的非负整数。
2
x
y
w
2\ x\ y\ w
2 x y w:对于所有
x
≤
i
≤
y
x≤i≤y
x≤i≤y,将
a
i
a_i
ai 修改为
w
w
w。其中
w
w
w 是一个小于
2
m
2^m
2m 的非负整数。
3
3
3:从
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an 中选出若干个数,使得选出的数异或和最大。请输出这个最大值。
题解:
将原序列差分,bi=ai^ai-1,每次区间异或就相当于修改两个数,区间赋值就相当于删除一些数,修改两个数,修改=删除+插入,瓶颈在于怎么在线性基中删一个数,维护每个数在序列出现的时间区间[li,ri],按时间轴扫过去,在线性基加入一个数时,从高位往低位,若现在可以插入第w位,第w位无值直接插入,有值假设这个值j的区间是[lj,rj],若rj<ri就把j取出来,i插入,把取出来的数接着往下插,这样删除一个数时可以直接从线性基中删掉他,基中没有其他数可以替代他的位置
这个思路对于很多难以删除的东西都是十分适用的,要好好记住。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=2010;
const int inf=2147483647;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
int n,m,q,R[Maxn],id[Maxn],cnt;//id[i] i位置上数的编号
bool mark[Maxn];
struct Node{bitset<Maxn>t;int l,r;}p[Maxn<<3];
char str[Maxn];
bitset<Maxn>a[Maxn],b[Maxn],c[Maxn],w,tmp;
void insert(int o)
{
tmp=p[o].t;
for(int i=m-1;i>=0;i--)
if(tmp[i])
{
if(R[i]<=p[o].l){c[i]=tmp;R[i]=p[o].r;return;}
if(R[i]<p[o].r)swap(R[i],p[o].r),swap(tmp,c[i]);
tmp^=c[i];
}
}
bitset<Maxn>re;
void query(int tim)
{
re.reset();
for(int i=m-1;i>=0;i--)
if(!re[i]&&R[i]>=tim)re^=c[i];
for(int i=m-1;i>=0;i--)
if(re[i])putchar('1');else putchar('0');
putchar('\n');
}
vector<int>h[Maxn];
int main()
{
memset(R,0,sizeof(R));
n=read(),m=read(),q=read();a[0].reset();cnt=n;
for(int i=1;i<=n;i++)
{
scanf("%s",str);
a[i].reset();
for(int j=0;j<m;j++)a[i][j]=str[m-j-1]-'0';
}
for(int i=1;i<=n;i++)
{
b[i]=a[i]^a[i-1];
id[i]=i;p[i].t=b[i];p[i].l=1,p[i].r=q;
}
for(int i=1;i<=q;i++)
{
int op=read();
if(op==3){mark[i]=true;continue;}
int x=read(),y=read();scanf("%s",str);
w.reset();
for(int j=0;j<m;j++)w[j]=str[m-j-1]-'0';
if(op==1)
{
for(int j=x;j<=y;j++)a[j]^=w;
p[id[x]].r=i;
b[x]^=w;
p[id[x]=++cnt].l=i,p[id[x]].r=q,p[id[x]].t=b[x];
if(y<n)
{
p[id[y+1]].r=i;
b[y+1]^=w;
p[id[y+1]=++cnt].l=i,p[id[y+1]].r=q,p[id[y+1]].t=b[y+1];
}
}
else
{
for(int j=x;j<=y;j++)a[j]=w;
p[++cnt].l=i;p[cnt].r=q;p[cnt].t.reset();
for(int j=x+1;j<=y;j++)
{
p[id[j]].r=i,b[j].reset();
id[j]=cnt;
}
p[id[x]].r=i;
b[x]=w^a[x-1];
p[id[x]=++cnt].l=i,p[id[x]].r=q,p[id[x]].t=b[x];
if(y<n)
{
p[id[y+1]].r=i;
b[y+1]=w^a[y+1];
p[id[y+1]=++cnt].l=i,p[id[y+1]].r=q,p[id[y+1]].t=b[y+1];
}
}
}
for(int i=1;i<=cnt;i++)h[p[i].l].push_back(i);
for(int i=1;i<=q;i++)
{
for(int j=0;j<h[i].size();j++)insert(h[i][j]);
if(mark[i])query(i);
}
}