锰锌刚学树链剖分1e-114514秒求救,WA20pts,悬赏3关注
查看原帖
锰锌刚学树链剖分1e-114514秒求救,WA20pts,悬赏3关注
501923
duchengjun楼主2022/12/24 09:23
#include<bits/stdc++.h>
using namespace std;
const int N=2*1e5+10,INF=2147483647;
struct Edge{
	int to,w;
};
vector<Edge>G[N];
int n,m;
int U[N],V[N];
int size[N],depth[N],fa[N],son[N],ans[N];
int top[N],id[N],rev[N],cnt;
int s[N<<2],mx[N<<2],mn[N<<2];
bool Opposite[N<<2];
char opt[10];
int u,v;
void DFS_Find_Son(int u){
	size[u]=1;
	depth[u]=depth[fa[u]]+1;
	for(int i=0;i<G[u].size();i++){
		Edge e=G[u][i];
		if(fa[u]==e.to)continue;
		fa[e.to]=u;
		ans[e.to]=e.w;
		DFS_Find_Son(e.to);
		size[u]+=size[e.to];
		if(size[son[u]]<size[e.to])
			son[u]=e.to;
	}
}
void DFS_Change(int u,int tp){
	top[u]=tp;
	id[u]=++cnt;
	rev[cnt]=u;
	if(son[u])
		DFS_Change(son[u],tp);
	for(int i=0;i<G[u].size();i++){
		Edge e=G[u][i];
		if(fa[u]==e.to||son[u]==e.to)continue;
		DFS_Change(e.to,e.to);
	}
}
void Up(int p){
	s[p]=s[p<<1]+s[p<<1|1];
	mx[p]=max(mx[p<<1],mx[p<<1|1]);
	mn[p]=min(mn[p<<1],mn[p<<1|1]);
}
void Down(int p){
	Opposite[p<<1]=!Opposite[p<<1];
	Opposite[p<<1|1]=!Opposite[p<<1|1];
	s[p<<1]=-s[p<<1];
	s[p<<1|1]=-s[p<<1|1];
	mx[p<<1]=-mx[p<<1];
	mn[p<<1]=-mn[p<<1];
	swap(mx[p<<1],mn[p<<1]);
	mx[p<<1|1]=-mx[p<<1|1];
	mn[p<<1|1]=-mn[p<<1|1];
	swap(mx[p<<1|1],mn[p<<1|1]);
	Opposite[p]=false;
}
void Build(int p,int l,int r){
	if(l==r){
		s[p]=mx[p]=mn[p]=ans[rev[l]];
		return;
	}
	int mid=(l+r)>>1;
	Build(p<<1,l,mid),Build(p<<1|1,mid+1,r);
	Up(p);
}
void Update_Change(int p,int l,int r,int x,int v){
	if(x<l||x>r)return;
	if(l==r){
		s[p]=mx[p]=mn[p]=v;
		return;
	}
	if(Opposite[p])Down(p);
	int mid=(l+r)>>1;
	Update_Change(p<<1,l,mid,x,v);
	Update_Change(p<<1|1,mid+1,r,x,v);
	Up(p);
}
void Update_Opposite(int p,int l,int r,int x,int y){
	if(l>y||x>r)return;
	if(x<=l&&r<=y){
		Opposite[p]=!Opposite[p];
		s[p]=-s[p];
		mx[p]=-mx[p];
		mn[p]=-mn[p];
		swap(mx[p],mn[p]);
		return;
	}
	if(Opposite[p])Down(p);
	int mid=(l+r)>>1;
	Update_Opposite(p<<1,l,mid,x,y);
	Update_Opposite(p<<1|1,mid+1,r,x,y);
	Up(p);
}
int Query_Sum(int p,int l,int r,int x,int y){
	if(l>y||x>r)return 0;
	if(x<=l&&r<=y)return s[p];
	if(Opposite[p])Down(p);
	int mid=(l+r)>>1;
	int sum=0;
	sum+=Query_Sum(p<<1,l,mid,x,y);
	sum+=Query_Sum(p<<1|1,mid+1,r,x,y);
	Up(p);
	return sum;
}
int Query_Max(int p,int l,int r,int x,int y){
	if(l>y||x>r)return -INF;
	if(x<=l&&r<=y)return mx[p];
	if(Opposite[p])Down(p);
	int mid=(l+r)>>1;
	int ans=-INF;
	ans=max(ans,Query_Max(p<<1,l,mid,x,y));
	ans=max(ans,Query_Max(p<<1|1,mid+1,r,x,y));
	Up(p);
	return ans;
}
int Query_Min(int p,int l,int r,int x,int y){
	if(l>y||x>r)return INF;
	if(x<=l&&r<=y)return mn[p];
	if(Opposite[p])Down(p);
	int mid=(l+r)>>1;
	int ans=INF;
	ans=min(ans,Query_Min(p<<1,l,mid,x,y));
	ans=min(ans,Query_Min(p<<1|1,mid+1,r,x,y));
	Up(p);
	return ans;
}
void Update_Change(int u,int v,int w){
	if(fa[u]==v)Update_Change(1,1,n,id[u],w);
	else Update_Change(1,1,n,id[v],w);
}
void Update_Opposite(int u,int v){
	if(top[u]!=top[v]){
		if(depth[top[u]]<depth[top[v]])swap(u,v);
		Update_Opposite(1,1,n,id[top[u]],id[u]);
		u=fa[top[u]];
	}
	if(id[u]>id[v])swap(u,v);
	if(u!=v)Update_Opposite(1,1,n,id[u]+1,id[v]);
}
int Query_Sum(int u,int v){
	int sum=0;
	while(top[u]!=top[v]){
		if(depth[top[u]]<depth[top[v]])swap(u,v);
		sum+=Query_Sum(1,1,n,id[top[u]],id[u]);
		u=fa[top[u]];
	}
	if(id[u]>id[v])swap(u,v);
	if(u!=v)sum+=Query_Sum(1,1,n,id[u]+1,id[v]);
	return sum;
}
int Query_Max(int u,int v){
	int ans=-INF;
	while(top[u]!=top[v]){
		if(depth[top[u]]<depth[top[v]])swap(u,v);
		ans=max(ans,Query_Max(1,1,n,id[top[u]],id[u]));
		u=fa[top[u]];
	}
	if(id[u]>id[v])swap(u,v);
	if(u!=v)ans=max(ans,Query_Max(1,1,n,id[u]+1,id[v]));
	return ans;
}
int Query_Min(int u,int v){
	int ans=INF;
	while(top[u]!=top[v]){
		if(depth[top[u]]<depth[top[v]])swap(u,v);
		ans=min(ans,Query_Min(1,1,n,id[top[u]],id[u]));
		u=fa[top[u]];
	}
	if(id[u]>id[v])swap(u,v);
	if(u!=v)ans=min(ans,Query_Min(1,1,n,id[u]+1,id[v]));
	return ans;
}
int main(){
	scanf("%d",&n);
	for(int i=1,w;i<=n-1;i++){
		scanf("%d%d%d",&U[i],&V[i],&w);
		U[i]++,V[i]++;
		G[U[i]].push_back(Edge{V[i],w});
		G[V[i]].push_back(Edge{U[i],w});
	}
	DFS_Find_Son(1);
	DFS_Change(1,1);
	Build(1,1,n);
	scanf("%d",&m);
	while(m--){
		scanf("%s%d%d",opt+1,&u,&v);
		if(opt[1]=='C'){
			Update_Change(U[u],V[u],v);
			continue;
		}
		u++,v++;
		if(opt[1]=='N')
			Update_Opposite(u,v);
		else if(opt[1]=='S')
			printf("%d\n",Query_Sum(u,v));
		else if(opt[2]=='A')
			printf("%d\n",Query_Max(u,v));
		else
			printf("%d\n",Query_Min(u,v));
	}
	return 0;
}
2022/12/24 09:23
加载中...