zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    beta冲刺1
    凡事预则立-于Beta冲刺前
    SDN第二次作业
    事后诸葛亮(团队)
    SDN第一次上机作业
    冲刺总结随笔
    Alpha第三天
    Alpha第二天
    Alpha冲刺博客集
    项目需求分析(团队)
  • 原文地址:https://www.cnblogs.com/nofind/p/12030878.html
Copyright © 2011-2022 走看看