首页 > 代码库 > [bzoj4644]经典傻逼题
[bzoj4644]经典傻逼题
话说这道题是因为ditoly大佬无聊时候想做sb题搜索了一下"傻逼题"搜到的,刚好今天学习了线性基,在ditoly大佬的帮助下做完啦。
------------------------------------------------------------------------------
题意:定义割操作是对于原图的一个点集,所有恰好只有一个点在集合中的边的集合,它的权值是所有边的异或和。
给定n个点,m个操作,每次向其中两个点中添加一条边,然后求一个最大的割的权值。n<=500 m<=1000 权值的二进制长度L<=1000
题解:首先很容易发现,我们把每个点的权值设成所有它在的边的权值异或和,原题转换为求一个最大异或和的点集,最大异或和我们考虑用线性基求出。
但是线性基不支持删除操作,我们考虑避免掉删除操作,具体实现就是采用线段树分治,对询问建一个时间轴就好啦。每次插入操作是L^2的,总复杂度mL^2logn
#include<iostream> #include<cstdio> #include<cstring> #include<bitset> #include<vector> #define ML 1000 using namespace std; inline 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 * 10 + ch - ‘0‘;ch = getchar();} return x * f; } int n,m,last[505]; struct node{int l,r;vector<bitset<1002> >s;vector<int>p;}T[4005]; bitset<1002> s[4005],now; char st[1005]; void build(int x,int l,int r) { if((T[x].l=l)==(T[x].r=r))return; int mid=l+r>>1; build(x<<1,l,mid);build(x<<1|1,mid+1,r); } void ins(int x,int l,int r,bitset<1002>&b) { // cout<<"ins"<<x<<" "<<l<<" "<<r<<endl; if(T[x].l==l&&T[x].r==r){T[x].s.push_back(b);return;} int mid=(T[x].l+T[x].r)>>1; if(r<=mid) ins(x<<1,l,r,b); else if(l>mid) ins(x<<1|1,l,r,b); else {ins(x<<1,l,mid,b);ins(x<<1|1,mid+1,r,b);} } void dfs(int x) { // cout<<"dfs"<<x<<endl; for(int i=0;i<T[x].s.size();i++) for(int j=1;j<=ML;j++) if(T[x].s[i][j]) if(!s[j][j]){s[j]=T[x].s[i];T[x].p.push_back(j);break;} else T[x].s[i]^=s[j]; if(T[x].l!=T[x].r) dfs(x<<1),dfs(x<<1|1); else { now.reset(); for(int i=1;i<=ML;i++) if(s[i][i]&&!now[i]) now^=s[i]; int j=1;for(;j<=ML&&!now[j];j++);if(j>ML) printf("0"); else for(;j<=ML;j++) printf("%d",now[j]?1:0); puts(""); } for(int i=0;i<T[x].p.size();i++) s[T[x].p[i]].reset(); } int main() { read();n=read();m=read(); build(1,1,m); for(int i=1;i<=m;i++) { int u=read(),v=read(); scanf("%s",st+1);if(u==v) continue; int len=strlen(st+1);now.reset(); for(int j=1;j<=len;j++) now[ML-len+j]=st[j]==‘1‘?1:0; if(last[u])ins(1,last[u],i-1,s[u]);last[u]=i; if(last[v])ins(1,last[v],i-1,s[v]);last[v]=i; s[u]^=now;s[v]^=now; } for(int i=1;i<=n;i++)if(last[i]<=m&&last[i]) ins(1,last[i],m,s[i]); for(int i=1;i<=n;i++)s[i].reset(); dfs(1); return 0; }
[bzoj4644]经典傻逼题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。