luoguP1505[国家集训队]旅游

树链剖分类模板:

#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define INF 0x7fffffff
#define CLR(a) memset(a, 0, sizeof(a))
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define MID(a,b) (a+((b-a)>>1))
const int maxn=2e5+10;
struct Edge{
	int nxt,to,val;
}edge[maxn]; 
int head[maxn],cnt,pt,w[maxn],wt[maxn];
int son[maxn],id[maxn],fa[maxn],dep[maxn],size[maxn],top[maxn]; 
void add(int u,int v,int val){
	edge[++cnt].to=v;
	edge[cnt].nxt=head[u];
	edge[cnt].val=val;
	head[u]=cnt;
}
struct node{
	int l,r,sum,Min,Max,lazy;
	int mid(){return MID(l,r);}
	void init(int tmp){
		sum=Min=Max=tmp;
	}
};
struct Segtree{
	node tree[maxn<<2];
	void push_up(int rt){
		tree[rt].sum=tree[ls].sum+tree[rs].sum;
		tree[rt].Max=max(tree[ls].Max,tree[rs].Max);
		tree[rt].Min=min(tree[ls].Min,tree[rs].Min);
	}
	void push_down(int rt){
		if(tree[rt].lazy){
			tree[ls].sum=-tree[ls].sum;tree[ls].lazy^=1;
			tree[rs].sum=-tree[rs].sum;tree[rs].lazy^=1;
			int p1,p2,p3,p4;
			p1=tree[ls].Min;
			p2=tree[ls].Max;
			p3=tree[rs].Min;
			p4=tree[rs].Max;
			tree[ls].Max=-p1;
			tree[ls].Min=-p2;
			tree[rs].Max=-p3;
			tree[rs].Min=-p4;
			tree[rt].lazy=0;
		}
	}
	void build(int l,int r,int rt){
		tree[rt].l=l;tree[rt].r=r; 
		if(l==r){
			tree[rt].init(wt[l]);
		}else{
			int mid=tree[rt].mid();
			build(l,mid,ls);
			build(mid+1,r,rs);
			push_up(rt);
		}
	}
	void update(int pos,int rt,int val){//单点更新 
		int l=tree[rt].l,r=tree[rt].r;
		if(l==r) tree[rt].init(val);
		else{
			push_down(rt);
			int mid=tree[rt].mid();
			if(pos<=mid) update(pos,ls,val);
			else update(pos,rs,val);
			push_up(rt);
		}
	}
	void modify(int st,int ed,int rt){//区间修改 
		int l=tree[rt].l,r=tree[rt].r;
		if(st<=l&&r<=ed){
			tree[rt].sum=-tree[rt].sum;
			tree[rt].lazy^=1;
			int p1,p2;
			p1=tree[rt].Max;
			p2=tree[rt].Min;
			tree[rt].Max=-p2;
			tree[rt].Min=-p1;
		}else{
			push_down(rt);
			int mid=tree[rt].mid();
			if(st<=mid) modify(st,ed,ls);
			if(ed>mid) modify(st,ed,rs);
			push_up(rt);
		}
	}
	int c_sum(int st,int ed,int rt){
		int l=tree[rt].l,r=tree[rt].r;
		if(st<=l&&r<=ed) return tree[rt].sum;
		else{
			push_down(rt);
			int mid=tree[rt].mid();
			int sum1=0,sum2=0;
			if(st<=mid) sum1=c_sum(st,ed,ls);
			if(ed>mid) sum2=c_sum(st,ed,rs);
			return sum1+sum2;
		}
	}
	int c_max(int st,int ed,int rt){
		int l=tree[rt].l,r=tree[rt].r;
		if(st<=l&&r<=ed) return tree[rt].Max;
		else{
			push_down(rt);
			int mid=tree[rt].mid();
			int mx1=-INF,mx2=-INF;//
			if(st<=mid) mx1=c_max(st,ed,ls);
			if(ed>mid) mx2=c_max(st,ed,rs);
			return max(mx1,mx2);
		}
	}
	int c_min(int st,int ed,int rt){
		int l=tree[rt].l,r=tree[rt].r;
		if(st<=l&&r<=ed) return tree[rt].Min;
		else{
			push_down(rt);
			int mid=tree[rt].mid();
			int mx1=INF,mx2=INF;//
			if(st<=mid) mx1=c_min(st,ed,ls);
			if(ed>mid) mx2=c_min(st,ed,rs);
			return min(mx1,mx2);
		}
	}
	void cal(int x,int y){
		int fx=top[x],fy=top[y];
		while(fx!=fy){
			if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
			modify(id[fx],id[x],1);//fx编号比x小,想想为什么? 
			x=fa[fx],fx=top[x];
		}
		if(id[x]>id[y]) swap(x,y);
		modify(id[x]+1,id[y],1);
	}
	int q_max(int x,int y){
		int fx=top[x],fy=top[y],ans=-INF;
		while(fx!=fy){
			if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
			ans=max(ans,c_max(id[fx],id[x],1));
			x=fa[fx],fx=top[x];
		}
		if(id[x]>id[y]) swap(x,y);
		return ans=max(ans,c_max(id[x]+1,id[y],1));
		
	}
	int q_min(int x,int y){
		int fx=top[x],fy=top[y],ans=INF;
		while(fx!=fy){
			if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
			ans=min(ans,c_min(id[fx],id[x],1));
			x=fa[fx],fx=top[x];
		}
		if(id[x]>id[y]) swap(x,y);
		return ans=min(ans,c_min(id[x]+1,id[y],1));
	}
	int q_sum(int x,int y){
		int fx=top[x],fy=top[y],ans=0;
		while(fx!=fy){
			if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
			ans+=c_sum(id[fx],id[x],1);
			x=fa[fx],fx=top[x];
		}
		if(id[x]>id[y]) swap(x,y);
		return ans+=c_sum(id[x]+1,id[y],1);
	}
}seg;
void dfs_1(int cur,int fath,int deep){
	dep[cur]=deep;
	fa[cur]=fath;
	size[cur]=1;
	int maxson=-1;
	for(int i=head[cur];i;i=edge[i].nxt){
		int to=edge[i].to;
		int val=edge[i].val;
		if(to==fath) continue;
		w[to]=val;
		dfs_1(to,cur,deep+1);
		size[cur]+=size[to];
		if(size[to]>maxson) son[cur]=to,maxson=size[to];
	} 
}
void dfs_2(int cur,int topf){
	id[cur]=++pt;
	wt[pt]=w[cur];
	top[cur]=topf;
	if(!son[cur]) return;
	dfs_2(son[cur],topf);
	for(int i=head[cur];i;i=edge[i].nxt){
		int to=edge[i].to;
		if(to==fa[cur]||to==son[cur]) continue;
		dfs_2(to,to);
	}
} 
int n;
int main() {
	int u,v,w;
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		scanf("%d%d%d",&u,&v,&w);
		u++,v++;
		add(u,v,w);
		add(v,u,w);
	}
	dfs_1(1,0,1);
	dfs_2(1,1);
	seg.build(1,n,1);
	int m;scanf("%d",&m);
	for(int i=1,x,y;i<=m;i++){
		char s1[10];
		scanf("%s%d%d",s1,&x,&y);
		x++,y++;
		if(s1[0]=='C') seg.update(id[x],1,y-1);
		if(s1[0]=='N') seg.cal(x,y);
		if(s1[0]=='S') printf("%d\n",seg.q_sum(x,y));
		if(s1[1]=='I') printf("%d\n",seg.q_min(x,y));
		if(s1[1]=='A') printf("%d\n",seg.q_max(x,y));
	}	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值