树链剖分模板

#include<cstdio>
#include<cstring>
#include<vector>
#include<istream>
#define ls u<<1,l,mid
#define rs u<<1|1,mid+1,r
#define maxn 100020
#define ll long long
using namespace std;
int n,m,head[2*maxn],hz[maxn],top[maxn],size[maxn],tot=1,cur[maxn],nu[maxn],vis[maxn],f[maxn],cnt,d[maxn];
struct edge{
	int v,next;
}e[maxn*2];
void adde(int a,int b){
	e[tot].v=b;
	e[tot].next=head[a];
	head[a]=tot++;
}

void dfs1(int u,int fa){
	size[u]=1;hz[u]=0,f[u]=fa,d[u]=d[fa]+1;
	for(int i=head[u];~i;i=e[i].next){
		int v=e[i].v;
		if(v==fa)continue;
		dfs1(v,u);
		size[u]+=size[v];
		if(size[v]>size[hz[u]])hz[u]=v;
	}
}
void dfs2(int u,int front){
	vis[u]=1;nu[u]=++cnt,top[u]=front;
	if(hz[u])dfs2(hz[u],front);
	for(int i=head[u];~i;i=e[i].next){
		int v=e[i].v;
		if(vis[v])continue;
		dfs2(v,v);
	}
}

struct node{
	int l,r;ll Max;
}nod[maxn*4];

void push_up(int u){nod[u].Max=max(nod[u<<1].Max,nod[u<<1|1].Max);}

void build(int u,int l,int r){
	nod[u].l=l,nod[u].r=r;
	if(l==r){
		nod[u].Max=0;return;
	}
	int mid=l+r>>1;
	build(rs);build(ls);
	push_up(u);
}

void update(int u,int l,int r,int x,ll add){
	if(l==r){
		nod[u].Max+=add;
		return;
	}
	int mid=l+r>>1;
	if(x>mid)update(rs,x,add);
	else update(ls,x,add);
	push_up(u);
}

ll query(int u,int l,int r,int x,int y){
	if(l==x&&r==y)return nod[u].Max;
	int mid=l+r>>1;
	if(x>mid)return query(rs,x,y);
	else if(y<=mid)return query(ls,x,y);
	else return max(query(ls,x,mid),query(rs,mid+1,y));
}

ll qmax(int a,int b){
	ll ans=-1e14;
	if(d[top[a]]>d[top[b]])swap(a,b);
	while(top[a]!=top[b]){
		if(d[top[a]]>d[top[b]]){
			ans=max(ans,query(1,1,cnt,nu[top[a]],nu[a]));
			a=f[top[a]];
		}else{
			ans=max(ans,query(1,1,cnt,nu[top[b]],nu[b]));
			b=f[top[b]];
		}
	}
	if(a!=b){
		if(nu[a]<nu[b])ans=max(ans,query(1,1,cnt,nu[a],nu[b]));
		else ans=max(ans,query(1,1,cnt,nu[b],nu[a]));
	}
	if(a==b)ans=max(ans,query(1,1,cnt,nu[a],nu[a]));
	return ans;
}

int main(){
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	for(int a,b,i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		adde(a,b);
		adde(b,a);
	}
	dfs1(1,1);
	dfs2(1,1);
	
	build(1,1,cnt);
	scanf("%d",&m);
	char s[4];
	int a;
	while(m--){
		scanf("%s",s);
		if(s[0]=='I'){
			ll b;
			scanf("%d%I64d",&a,&b);
			update(1,1,cnt,nu[a],b);
		}else if(s[0]=='G'){
			int b;
			scanf("%d%d",&a,&b);
			printf("%I64d\n",qmax(a,b));
		}
	}
	return 0;
}/*
10
1 2
2 4
4 6
4 7
6 10
1 3
3 8
3 5
5 9

*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值