CF938G Shortest Path Queries

题意

前置题目:P4151 [WC2011]最大XOR和路径

线段树分治维护边集,用可撤销的并查集维护生成树和每个点到根的异或和,线性基查最小值。

code:

#include<bits/stdc++.h>
using namespace std;
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
const int maxn=200010;
const int maxm=200010;
const int maxQ=200010;
int n,m,Q,tot,cnt,top;
int fa[maxn],size[maxn],dis[maxn],ans[maxQ];
vector<int>seg[maxQ<<2];
map<pii,int>mp;
struct Edge{int u,v,w,st,ed;}E[maxm+maxQ];
struct Query{int x,y;}qr[maxQ];
struct node{int x,y;}sta[maxm+maxQ];
struct Xord
{
	int d[35];
	inline void clear(){memset(d,0,sizeof(d));}
	inline void insert(int x)
	{
		for(int i=30;~i;i--)
		{
			if(!(x&(1<<i)))continue;
			if(!d[i]){d[i]=x;return;}
			else x^=d[i]; 
		}
	}
	inline int query(int x)
	{
		int res=x;
		for(int i=30;~i;i--)if(res>(res^d[i]))res^=d[i];
		return res;		
	} 
}xord;
inline int read()
{
	char c=getchar();int res=0,f=1;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
	return res*f;
}
int find(int x){return fa[x]==x?x:find(fa[x]);}
int getdis(int x){return fa[x]==x?dis[x]:dis[x]^getdis(fa[x]);}
inline void cut(int id)
{
    int x=sta[id].x,y=sta[id].y;
    fa[x]=x;dis[x]=0;size[y]-=size[x];
}
void change(int p,int l,int r,int ql,int qr,int id)
{
	if(ql>qr)return;
	if(l>=ql&&r<=qr){seg[p].push_back(id);return;}
	int mid=(l+r)>>1;
	if(ql<=mid)change(ls(p),l,mid,ql,qr,id);
	if(qr>mid)change(rs(p),mid+1,r,ql,qr,id);
}
void solve(int p,int l,int r,Xord xord)
{
	int now=top;
	for(unsigned int i=0;i<seg[p].size();i++)
	{
        int id=seg[p][i],u,v,w,x,y;
        u=E[id].u,v=E[id].v,w=E[id].w;
        x=find(u),y=find(v);
        w^=getdis(u)^getdis(v);
        if(x==y)xord.insert(w);
        else 
        {
            if(size[x]>size[y])swap(x,y);
            fa[x]=y;size[y]+=size[x];dis[x]=w;
            sta[++top]=(node){x,y};
        }
	}
	//cerr<<l<<' '<<r<<endl;
	if(l==r)ans[l]=xord.query(getdis(qr[l].x)^getdis(qr[l].y));
	else 
	{
		int mid=(l+r)>>1;
		solve(ls(p),l,mid,xord);solve(rs(p),mid+1,r,xord);
	}
	while(top>now)cut(top),top--;
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)fa[i]=i,size[i]=1,dis[i]=0;
	for(int i=1;i<=m;i++)
	{
		E[i].u=read(),E[i].v=read(),E[i].w=read();
		E[i].st=1;E[i].ed=-1;
		mp[mkp(E[i].u,E[i].v)]=i;
	}
	tot=m;
	Q=read();
	for(int i=1;i<=Q;i++)
	{
		int op=read(),x=read(),y=read(),k;
		if(op==1)
		{
			k=read();
			E[++tot]=(Edge){x,y,k,cnt+1,-1};
			mp[mkp(x,y)]=tot;
		}
		if(op==2)
		{
			int id=mp[mkp(x,y)];
			E[id].ed=cnt;
		}
		if(op==3)qr[++cnt]=(Query){x,y};
	}
	for(int i=1;i<=tot;i++)if(E[i].ed==-1)E[i].ed=cnt;
	for(int i=1;i<=tot;i++)change(1,1,cnt,E[i].st,E[i].ed,i);
	solve(1,1,cnt,xord);
	for(int i=1;i<=cnt;i++)printf("%d
",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/nofind/p/12030878.html