首页 > 其他分享 >P2590 [ZJOI2008]树的统计

P2590 [ZJOI2008]树的统计

时间:2023-03-10 22:36:35浏览次数:41  
标签:return int res top tr son P2590 ZJOI2008 统计

一棵树上有 n个节点,编号分别为 1 到 n,每个节点都有一个权值 W。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点 u的权值改为 t。

II. QMAX u v: 询问从点 u到点 v 的路径上的节点的最大权值。

III. QSUM u v: 询问从点 u 到点 v 的路径上的节点的权值和。

 

#include <bits/stdc++.h>
using namespace std ;
 const int N=5e5+4,M=N*2;
  
 #define inf 1e9
 
 int n,nxt[M],hd[N],all,go[M],w[M];
 int dep[N],sz[N],fa[N],son[N];
 int dfn[N],id[N],pool,top[N];
 
 void add_(int x,int y){
 	go[++all]=y;
 	nxt[all]=hd[x],hd[x]=all;
 }
 
#define k1 k<<1
#define k2 k<<1|1

  int a[N];
  struct Tree{
    int sum,mx;
  	int l,r;
  }tr[N<<2];
 
 void up(int k){
 	tr[k].sum=tr[k1].sum+tr[k2].sum;
 	tr[k].mx=max(tr[k1].mx,tr[k2].mx);
 }
 void add(int k,int x,int v){
 	if(tr[k].l==tr[k].r){
 		tr[k].sum=v; tr[k].mx=v;
 		return;
 	}
 	int md=(tr[k].l+tr[k].r)/2; 
 	if(x<=md) add(k1,x,v);
 	else add(k2,x,v);
 	up(k);
 }
 
 int qmax(int k,int x,int y){
 	int t= -inf;
     if(x<=tr[k].l&&y>=tr[k].r)
         return tr[k].mx;
     
     int md=(tr[k].l+tr[k].r)/2; 
     if(x<=md) t=max(t,qmax(k1,x,y));
     if(y>md) t=max(t,qmax(k2,x,y));
     return t;
 }
 int qsum(int k,int x,int y){
     int t=0;
     if(x<=tr[k].l&&y>=tr[k].r)
         return tr[k].sum;
     
     int md=(tr[k].l+tr[k].r)/2; 
    
     if(x<=md) t+=qsum(k1,x,y);
     if(y>md) t+=qsum(k2,x,y);
     return t;
 }
 
 void build(int k,int l,int r){
 	tr[k].l=l,tr[k].r=r;
 	tr[k].sum=0;  tr[k].mx= -inf;
 	
     if(l==r){
         tr[k].sum=tr[k].mx=a[id[l]];  return;
     }
     int md=(l+r)/2;
     build(k1,l,md),build(k2,md+1,r);
     
     up(k);
 }

 
 
 void dfs1(int x,int par){
 	fa[x]=par;
 	sz[x]=1;
 	dep[x]=dep[par]+1;
 	son[x]=0;
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; if(par==y) continue;
 			
		dfs1(y,x);
 		sz[x]+=sz[y];
 		if(sz[y]>sz[son[x]]) son[x]=y;
	 }
 }
 void dfs2(int x,int topf){
 	dfn[x]=++pool;
 	id[pool]=x;
 	top[x]=topf;
 	if(!son[x]) return ;
 	dfs2(son[x],topf);
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; 
 		if(y==fa[x]||y==son[x]) continue;
		  dfs2(y,y);
	 }
 }

 void upNode(int x,int v){
 	add(1,dfn[x],v);
 }
 int R_qMax(int x,int y){
 	int res=-inf;
 	while(top[x]!=top[y]){
 		if(dep[top[x]]<dep[top[y]]) swap(x,y);
 		res=max(res, qmax(1,dfn[top[x]],dfn[x]));
 		
 		x=fa[top[x]];
	 }
	if(dep[x]>dep[y]) swap(x,y);
	res=max(res, qmax(1,dfn[x],dfn[y])) ;  //
	return res;
 }
 int R_qSum(int x,int y){
 	int res=0;
 	while(top[x]!=top[y]){
 		if(dep[top[x]]<dep[top[y]]) swap(x,y);
 		res+=qsum(1,dfn[top[x]],dfn[x]);
 		
 		x=fa[top[x]];
	 }
	if(dep[x]>dep[y]) swap(x,y);
	res+=qsum(1,dfn[x],dfn[y]) ;
	return res;
 }
 signed main(){
 	cin>>n;
 	int i,x,y,tes;
 	string op;
 	for(i=1;i<n;i++)cin>>x>>y,add_(x,y),add_(y,x);
 	for(i=1;i<=n;i++) cin>>a[i];
 	
 	dfs1(1,0); dfs2(1,1);build(1,1,n) ;
 	cin>>tes;
 	
 	while(tes--){
 		cin>>op>>x>>y;
 		if(op=="QMAX") cout<<R_qMax(x,y)<<endl;
 		else if(op=="CHANGE") upNode(x,y);
 		else if(op=="QSUM") cout<<R_qSum(x,y)<<endl;
 	}
 } 

 

标签:return,int,res,top,tr,son,P2590,ZJOI2008,统计
From: https://www.cnblogs.com/towboa/p/17204830.html

相关文章