1. 程式人生 > >bzoj4644: 經典傻逼題

bzoj4644: 經典傻逼題

dfs lib lag urn eof space d+ 相同 truct

我是弟弟。。。左左睿的神題還是另外一題的真子集

首先令點權為和它相連的邊權異或和,容易發現一個點集的割就是點權和

但是m次線性基肯定是不行的

學了個新東西,線段樹分治

首先他的下標是時間

對於一個點,他的權值反映在時間軸上就是多段權值

然後插入到線段樹上,容易證明如果是一段相同的權值,最多會被拆成logn段

對於每一段直接在管理節點上面開個vector記錄,相當於這是他的子節點共用的

最後遍歷整棵樹,到達一個點就把它上面的插進線性基,回溯就清空

#include<cstdio>
#include<iostream>
#include<cstring>
#include
<cstdlib> #include<algorithm> #include<cmath> #include<bitset> #include<vector> using namespace std; struct node { int l,r,lc,rc; vector< bitset<1100> >s; vector<int>clear; }tr[4100];int trlen,last[510]; void bt(int l,int r) {
int now=++trlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=-1; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); } } bitset<1100>lt[1100],t; void insert(int now,int l,int r,int p) { if(tr[now].l==l&&tr[now].r==r) { tr[now].s.push_back(lt[p]);
return ; } int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; if(r<=mid) insert(lc,l,r,p); else if(mid+1<=l)insert(rc,l,r,p); else insert(lc,l,mid,p),insert(rc,mid+1,r,p); } void add(int now,int o)//線性基 { for(int i=1;i<=1000;i++) if(tr[now].s[o][i]) { if(!lt[i][i]) { lt[i]=tr[now].s[o]; tr[now].clear.push_back(i); break; } else tr[now].s[o]^=lt[i]; } } void getmax() { t.reset(); for(int i=1;i<=1000;i++) if(!t[i])t^=lt[i]; bool flag=false; for(int i=1;i<=1000;i++) { if(t[i]==1)flag=true; if(t[i]|flag) printf("%d",(t[i]==1)); } if(flag==false)printf("0"); printf("\n"); } void dfs(int now) { for(int i=0;i<tr[now].s.size();i++)add(now,i); if(tr[now].l==tr[now].r)getmax(); else dfs(tr[now].lc),dfs(tr[now].rc); for(int i=0;i<tr[now].clear.size();i++)lt[tr[now].clear[i]].reset(); } char ss[1100];int sslen; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int ID,n,m,x,y; scanf("%d%d%d",&ID,&n,&m); trlen=0;bt(1,m); memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) { scanf("%d%d%s",&x,&y,ss+1);sslen=strlen(ss+1); if(x==y)continue; t.reset(); for(int j=1;j<=sslen;j++) t[1000-sslen+j]=(ss[j]==1); if(last[x]!=0)insert(1,last[x],i-1,x); last[x]=i; if(last[y]!=0)insert(1,last[y],i-1,y); last[y]=i; lt[x]^=t; lt[y]^=t; } for(int i=1;i<=n;i++) if(last[i]!=0&&last[i]<=m)insert(1,last[i],m,i); for(int i=1;i<=n;i++)lt[i].reset(); dfs(1); return 0; }

bzoj4644: 經典傻逼題