1. 程式人生 > >[LOJ]#2312. 「HAOI2017」八縱八橫 線段樹分治+線性基

[LOJ]#2312. 「HAOI2017」八縱八橫 線段樹分治+線性基

題解:

如果你做過[Wc2011] Xor,你就會知道,這個求的實際上是由所有環的異或值構成的線性基的最大值,知道這個就可以用線段樹分治搞了。由於線性基不能刪除,所以我採用了一個非常暴力的方法,在訪問兒子節點時記錄下當前的線性基,結束當前節點往上時再把線性基還原,寫得有點傻,又長又慢……

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=510,Maxl=1010,Maxq=1010;
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; } bitset<Maxl>a[Maxl],val[Maxn],ans,tmp[15][Maxl]; int n,m,P;bool vis[
Maxn]; struct Edge{int x,y,next;bitset<Maxl>d;}e[Maxn<<1]; int last[Maxn],len=0; void ins(int x,int y,bitset<Maxl>d) { int t=++len; e[t].y=y;e[t].d=d;e[t].next=last[x];last[x]=t; } char s[Maxl]; void Read(bitset<Maxl>&w) { scanf("%s",s); int len=strlen(s); w.reset(); for
(int i=0;i<len;i++)w[i]=s[len-i-1]-'0'; } void insert(bitset<Maxl>w) { if(!w.count())return; for(int i=1000;i>=0;i--) if(w[i]) { if(!a[i].count()){a[i]=w;return;} w^=a[i]; } } void print(bitset<Maxl>w) { bool flag=false; for(int i=1000;i>=0;i--) { if(!flag&&!w[i])continue; flag=true;cout<<w[i]; }putchar('\n'); } void dfs(int x) { vis[x]=true; for(int i=last[x];i;i=e[i].next) { int y=e[i].y; if(!vis[y])val[y]=val[x]^e[i].d,dfs(y); else insert(val[y]^val[x]^e[i].d); } } vector<int>h[Maxq<<2];int id[Maxq],tot=0,L[Maxq],R[Maxq],cnt=0,Add=0; void Insert(int x,int l,int r,int ql,int qr,int p) { if(ql==l&&qr==r){h[x].push_back(p);return;} int lc=x<<1,rc=(x<<1)|1,mid=l+r>>1; if(qr<=mid)Insert(lc,l,mid,ql,qr,p); else if(ql>mid)Insert(rc,mid+1,r,ql,qr,p); else Insert(lc,l,mid,ql,mid,p),Insert(rc,mid+1,r,mid+1,qr,p); } bool use[Maxn]; int get() { for(int i=1;;i++) if(!use[i])return i; } void work(int x,int l,int r) { int now=get();use[now]=true; for(int i=1000;i>=0;i--)tmp[now][i]=a[i]; for(int i=0;i<h[x].size();i++) { int t=h[x][i]; insert(val[e[t].x]^val[e[t].y]^e[t].d); } if(l==r) { ans.reset(); for(int i=1000;i>=0;i--) if(a[i].count()&&!ans[i])ans^=a[i]; print(ans); for(int i=1000;i>=0;i--)a[i]=tmp[now][i]; use[now]=false; return; } int lc=x<<1,rc=(x<<1)|1,mid=l+r>>1; work(lc,l,mid),work(rc,mid+1,r); use[now]=false; for(int i=1000;i>=0;i--)a[i]=tmp[now][i]; } int main() { n=read(),m=read(),P=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); bitset<Maxl>d;Read(d); ins(x,y,d),ins(y,x,d); } val[1].reset();dfs(1); ans.reset(); for(int i=1000;i>=0;i--) if(a[i].count()&&!ans[i])ans^=a[i]; print(ans); if(!P)return 0; for(int i=1;i<=P;i++) { char op[10]; scanf("%s",op); if(op[1]=='d'){Add++;id[Add]=++tot;L[tot]=i,R[tot]=P;e[tot].x=read();e[tot].y=read();Read(e[tot].d);} else if(op[1]=='h') { int x=read(),t=id[x]; R[t]=i-1;id[x]=++tot; L[tot]=i,R[tot]=P;e[tot].x=e[t].x,e[tot].y=e[t].y,Read(e[tot].d); } else R[id[read()]]=i-1; } for(int i=1;i<=tot;i++)Insert(1,1,P,L[i],R[i],i); work(1,1,P); }