CF 938 G Shortest Path Queries(线性基,线段树分治)

题目
太模板了,没啥好说的

#include<bits/stdc++.h>
#define maxn 800005
#define pii pair<int,int>
#define mp make_pair
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
	char ch;
	for(;!isdigit(ch=getc()););
	for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}

int n,m,q;
int F[maxn],sz[maxn],H[maxn],qx[maxn],qy[maxn],qw[maxn],qt[maxn];
map<pii,int>mAp;
pii Find(int u){
	if(!F[u]) return mp(u,0);
	pii t = Find(F[u]);
	t.second ^= H[u];
	return t;
}

struct Base{
	int a[30];
	void ins(int x){
		for(int i=29;i>=0&&x;i--)
			if(x>>i&1){
				if(a[i]) x ^= a[i];
				else{
					a[i] = x;
					break;
				}
			}
	}
	int qry(int x){
		per(i,29,0) if((x ^ a[i]) < x)
			x ^= a[i];
		return x;
	}
}T[maxn<<2];

vector<int>G[maxn<<2];
int ans[maxn],Qx[maxn],Qy[maxn];

#define lc u<<1
#define rc lc|1
void ins(int u,int l,int r,int ql,int qr,int v){
	if(l>qr||ql>r) return;
	if(ql<=l&&r<=qr) return (void)(G[u].push_back(v));
	int m=l+r>>1;
	ins(lc,l,m,ql,qr,v),ins(rc,m+1,r,ql,qr,v);
}

void Solve(int u,int l,int r){
	vector<int>mdfd;
	rep(i,0,G[u].size()-1){
		int x = qx[G[u][i]] , y = qy[G[u][i]] , w = qw[G[u][i]];
		pii dx = Find(x) , dy = Find(y);
		if(dx.first != dy.first){
			if(sz[dx.first] > sz[dy.first]) swap(dx,dy);
			mdfd.push_back(dx.first);
			F[dx.first] = dy.first;
			sz[dy.first] += sz[dx.first];
			H[dx.first] = dx.second ^ dy.second ^ w;
		}
		else{
			T[u].ins(dx.second ^ dy.second ^ w);
		}
	}
	
	if(l==r){
		if(Qx[l]){
			pii dx = Find(Qx[l]) , dy = Find(Qy[l]);
			ans[l] = T[u].qry(dx.second ^ dy.second);
		}
	}
	else{
		int m=l+r>>1;
		T[lc] = T[rc] = T[u];
		Solve(lc,l,m),Solve(rc,m+1,r);
	}
	per(i,mdfd.size()-1,0){
		int u = mdfd[i] , v = F[u];
		F[u] = 0 , sz[v] -= sz[u] , H[u] = 0;
	}
}

int main(){
	read(n),read(m);
	rep(i,1,n) sz[i] = 1;
	rep(i,1,m) read(qx[i]),read(qy[i]),read(qw[i]),mAp[mp(min(qx[i],qy[i]),max(qx[i],qy[i]))] = i,qt[i] = 1;
	memset(ans,-1,sizeof ans);
	read(q);
	rep(i,1,q){
		static int op , x , y , d;
		read(op),read(x),read(y);
		if(op == 1){
			read(d);
			++m;
			qx[m] = x , qy[m] = y , qw[m] = d , qt[m] = i;
			mAp[mp(min(qx[m],qy[m]),max(qx[m],qy[m]))] = m;
		}
		if(op == 2){
			if(x > y) swap(x,y);
			int u = mAp[mp(x,y)];
			ins(1,1,q,qt[u],i,u);
			mAp.erase(mp(x,y));
		}
		if(op == 3)
			Qx[i] = x , Qy[i] = y;
	}
	for(map<pii,int>::iterator it = mAp.begin();it != mAp.end();it++){
		int u = (*it).second;
		ins(1,1,q,qt[u],q,u);
	}
	Solve(1,1,q);
	rep(i,1,q) if(Qx[i])
		printf("%d\n",ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值