影片連結:C141 線段樹分治+線性基 P3733 [HAOI2017] 八縱八橫_嗶哩嗶哩_bilibili
P3733 [HAOI2017] 八縱八橫 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)
// 線段樹分治+線性基 O(q*logq*logL*logL) #include <iostream> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namespace std; #define ls (u<<1) #define rs (u<<1|1) #define mid (l+r>>1) const int N=1005; typedef bitset<N> bit; vector<bit> tr[N<<2]; //節點 bit sum[N],val[N]; int n,m,q,x,y,k; char s[N],z[N]; int vis[N],tim[N],cnt; int head[N],idx; struct edge{ int to,ne; bit w; }e[N<<1]; //原邊 struct edge2{ int x,y; }a[N<<1]; //新邊 bit p[N]; //初始的線性基 void add(int x,int y,bit w){ e[++idx].to=y; e[idx].ne=head[x]; e[idx].w=w; head[x]=idx; } void print(bit a[]){ int i,j; bit c; for(i=1000;i>=0&&!a[i].any();i--) if(i<0){puts("0");return;} for(j=i;j>=0;j--) if(a[j].any()&&!c[j]) c^=a[j]; for(j=i;j>=0;j--) putchar('0'+c[j]); puts(""); } void insert(bit a[],bit x){ //插入線性基 if(!x.any()) return; for(int i=1000;i>=0;i--){ if(x[i]){ if(!a[i].any()){ a[i]=x; break; } x^=a[i]; } } } void dfs(int x){ vis[x]=1; for(int i=head[x];i;i=e[i].ne){ int y=e[i].to; if(!vis[y]) sum[y]=sum[x]^e[i].w,dfs(y); else insert(p,sum[x]^e[i].w^sum[y]); } } void ins(int u,int l,int r,int L,int R,bit x){ if(l>R||r<L) return; if(L<=l&&r<=R){ tr[u].push_back(x); return; } ins(ls,l,mid,L,R,x); ins(rs,mid+1,r,L,R,x); } void solve(int u,int l,int r,bit a[]){ bit b[N]; for(int i=1000;i>=0;i--) b[i]=a[i]; for(auto i:tr[u]) insert(b,i); //插入基 if(l==r){ print(b); return; } solve(ls,l,mid,b); solve(rs,mid+1,r,b); } int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++){ scanf("%d%d%s",&x,&y,z); bit w(z); add(x,y,w); add(y,x,w); } dfs(1); print(p); for(int i=1;i<=q;i++){ scanf("%s",s); if(s[1]=='d'){ //Add scanf("%d%d%s",&x,&y,z); tim[++cnt]=i; //第k號邊的出現時刻 bit w(z); a[cnt]={x,y}; val[cnt]=sum[x]^sum[y]^w; //環值 } else if(s[1]=='h'){ //Change scanf("%d%s",&k,z); ins(1,1,q,tim[k],i-1,val[k]); //插入樹 tim[k]=i; //第k號邊的出現時刻 bit w(z); val[k]=sum[a[k].x]^sum[a[k].y]^w; //環值 } else{ //Cancel scanf("%d",&k); ins(1,1,q,tim[k],i-1,val[k]); //插入樹 tim[k]=q+1; //第k號邊消失 } } for(int i=1;i<=cnt;i++) ins(1,1,q,tim[i],q,val[i]); //插入樹 if(q) solve(1,1,q,p); //分治 }
// 線段樹分治+線性基 O(q*logq*logL*logL) #include <iostream> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namespace std; #define ls (u<<1) #define rs (u<<1|1) #define mid (l+r>>1) const int N=1005; typedef bitset<N> bit; vector<bit> tr[N<<2]; //節點 bit sum[N],val[N]; int n,m,q,x,y,k; char s[N],z[N]; int vis[N],tim[N],cnt; int head[N],idx; struct edge{ int to,ne; bit w; }e[N<<1]; //原邊 struct edge2{ int x,y; }a[N<<1]; //新邊 struct bs{ bit b[N]; }p; //初始的線性基 void add(int x,int y,bit w){ e[++idx].to=y; e[idx].w=w; e[idx].ne=head[x]; head[x]=idx; } void print(bs &a){ int i,j; bit c; for(i=1000;i>=0&&!a.b[i].any();i--) if(i<0){puts("0");return;} for(j=i;j>=0;j--) if(a.b[j].any()&&!c[j]) c^=a.b[j]; for(j=i;j>=0;j--) putchar('0'+c[j]); puts(""); } void insert(bs &a,bit x){ //注意bs傳地址 if(!x.any()) return; for(int i=1000;i>=0;i--){ if(x[i]){ if(!a.b[i].any()){ a.b[i]=x; break; } x^=a.b[i]; } } } void dfs(int x){ vis[x]=1; for(int i=head[x];i;i=e[i].ne){ int y=e[i].to; if(!vis[y]) sum[y]=sum[x]^e[i].w,dfs(y); else insert(p,sum[x]^e[i].w^sum[y]); } } void ins(int u,int l,int r,int L,int R,bit x){ if(l>R||r<L) return; if(L<=l&&r<=R){ tr[u].push_back(x); return; } ins(ls,l,mid,L,R,x); ins(rs,mid+1,r,L,R,x); } void solve(int u,int l,int r,bs a){ //注意bs傳值 for(auto i:tr[u]) insert(a,i); //插入基 if(l==r){ print(a); //輸出 return; } solve(ls,l,mid,a); solve(rs,mid+1,r,a); } int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++){ scanf("%d%d%s",&x,&y,z); bit w(z); add(x,y,w); add(y,x,w); } dfs(1); print(p); for(int i=1;i<=q;i++){ scanf("%s",s); if(s[1]=='d'){ //Add scanf("%d%d%s",&x,&y,z); tim[++cnt]=i; //第k號邊的出現時刻 bit w(z); a[cnt]={x,y}; val[cnt]=sum[x]^sum[y]^w; //環值 } else if(s[1]=='h'){ //Change scanf("%d%s",&k,z); ins(1,1,q,tim[k],i-1,val[k]); //插入樹 tim[k]=i; //第k號邊的出現時刻 bit w(z); val[k]=sum[a[k].x]^sum[a[k].y]^w; //環值 } else{ //Cancel scanf("%d",&k); ins(1,1,q,tim[k],i-1,val[k]); //插入樹 tim[k]=q+1; //第k號邊消失 } } for(int i=1;i<=cnt;i++) ins(1,1,q,tim[i],q,val[i]); //插入樹 if(q) solve(1,1,q,p); //分治 }