标签:a.out res back eof ret str 时间轴 sizeof names
我是弟弟。。。左左睿的神题还是另外一题的真子集
首先令点权为和它相连的边权异或和,容易发现一个点集的割就是点权和
但是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; }
标签:a.out res back eof ret str 时间轴 sizeof names
原文地址:https://www.cnblogs.com/AKCqhzdy/p/10196492.html