[LOJ]#2312. 「HAOI2017」八纵八横 线段树分治+线性基

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/85311280

题解:

如果你做过[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);
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/85311280