CF938G Shortest Path Queries
题意
线段树分治维护边集,用可撤销的并查集维护生成树和每个点到根的异或和,线性基查最小值。
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\n",ans[i]);
return 0;
}