【学习笔记】【集训队互测2015】最大异或和
这题大概有
N
O
I
NOI
NOI的
t
1
t1
t1难度。但是我维护的东西和正解恰好是反的啊啊啊
离线的做法太难想到了。注意到 n , m n,m n,m同阶,这看着非常亲切,因为意味着我们可以每次修改直接暴力维护,而不需要什么复杂度数据结构去平衡它。
将原序列差分,很容易想到维护一个支持插入,删除的线性基。我们不妨先给出算法流程,然后再来验证其复杂度。在 S A M SAM SAM中我们也是这么干的。
考虑用线性基维护,哪些数在线性基中,以及维护的每个线性基如何用它们表示,不在线性基中的数如何用基底表示。注意,这里的基底指的是原数。
然后分类讨论。设删除的数是 x x x,如果 x x x不是基底那么直接删除即可。否则如果存在 y y y不在基底中,并且其基底表示中有 x x x,那么就可以用 y y y来替代 x x x,显然基底张成的空间不变,那么线性基也不变,但是表示方式变了。如果不存在这样的 y y y,那么意味着基底的数目会减少 1 1 1,考虑消去 x x x对线性基的影响,但是注意到我们要保证最高位 1 1 1具有单调性,那么考虑找到最小的包含 x x x的线性基 z z z,这样 z z z向上消的时候最高位 1 1 1就不会发生变化,将线性基 z z z删除即可。因为是对原来的基进行线性变换所以剩下 k − 1 k-1 k−1个线性基显然也是线性无关的。
复杂度 O ( n 3 w ) O(\frac{n^3}{w}) O(wn3)。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
int n,m,Q,type,state[2005];
bitset<2005>base[2005],a[2005];
bitset<2005>bs[2005],bi[2005];
void add(int x){
if(x>n||a[x]==a[x-1])return;
bi[x].reset();
state[x]=0;
bitset<2005>tmp;
tmp=a[x]^a[x-1];
for(int i=0;i<m;i++){
if(tmp[i]){
if(base[i][i]){
bi[x]^=bs[i];
tmp^=base[i];
}
else{
base[i]=tmp;
bs[i]=bi[x];
bs[i][x]=1;
state[x]=1;
return;
}
}
}
}
void del(int x){
if(x>n||a[x]==a[x-1])return;
if(!state[x]){
bi[x].reset();
return;
}
bitset<2005>tmp;
tmp=a[x]^a[x-1];
for(int i=1;i<=n;i++){
if(!state[i]&&bi[i][x]){
bi[i][i]=1;
state[i]=1;
state[x]=0;
bi[x].reset();
for(int j=0;j<m;j++){
if(bs[j][x]){
bs[j]^=bi[i];
}
}
for(int j=1;j<=n;j++){
if(!state[j]&&bi[j][x]){
bi[j]^=bi[i];
}
}
return;
}
}
int z=m-1;while(z>=0&&bs[z][x]==0)z--;
for(int i=0;i<z;i++){
if(bs[i][x]){
bs[i]^=bs[z];
base[i]^=base[z];
}
}
base[z]=0;
bs[z].reset();
state[x]=0;
bi[x].reset();
}
void query(){
bitset<2005>tmp;
for(int j=0;j<m;j++){
if(base[j][j]&&!tmp[j]){
tmp^=base[j];
}
}
for(int j=0;j<m;j++)cout<<tmp[j];
cout<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>Q;
for(int i=1;i<=n;i++){
string str;cin>>str;
for(int j=0;j<m;j++){
a[i][j]=str[j]-'0';
}
}
for(int i=1;i<=n;i++){
add(i);
}
for(int i=1;i<=Q;i++){
int type;
cin>>type;
if(type==1){
bitset<2005>tmp;
int l,r;string str;
cin>>l>>r>>str;
for(int j=0;j<m;j++){
tmp[j]=str[j]-'0';
}
del(l),del(r+1);
for(int j=l;j<=r;j++)a[j]^=tmp;
add(l),add(r+1);
}
else if(type==2){
bitset<2005>tmp;
int l,r;string str;
cin>>l>>r>>str;
for(int j=0;j<m;j++){
tmp[j]=str[j]-'0';
}
for(int j=l;j<=r+1;j++)del(j);
for(int j=l;j<=r;j++)a[j]=tmp;
add(l),add(r+1);
}
else if(type==3){
query();
}
}
}

浙公网安备 33010602011771号