【学习笔记】【集训队互测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 k1个线性基显然也是线性无关的。

复杂度 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(); } } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17529966.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(31)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2022-06-03 杂题选做。
2022-06-03 构造题专练
点击右上角即可分享
微信分享提示