树的统计

Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

动态树的题目似乎都大同小异啊。

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 30005
using namespace std;
int ch[MAXN][2],fa[MAXN],sum[MAXN],maxz[MAXN],val[MAXN];
char opt[10];
bool rev[MAXN],tp[MAXN];
int n,q;
struct bian
{
    int u,v;
}e[MAXN];
void getint(int &num)
{
    num=0;
    char c;
    int flag=1;
    while((c=getchar())&&!isdigit(c))if(c=='-')flag=-1;
    while(isdigit(c)){num=num*10+c-48;c=getchar();
    }
    num*=flag;
}
void pushdown(int r)
{
    if(rev[r])
    {rev[r]=0;
     swap(ch[r][0],ch[r][1]);
     if(ch[r][0])rev[ch[r][0]]^=1;
     if(ch[r][1])rev[ch[r][1]]^=1; 
    }
}
void pushup(int r)
{
sum[r]=sum[ch[r][0]]+sum[ch[r][1]]+val[r];
maxz[r]=val[r];
if(ch[r][0])maxz[r]=max(maxz[ch[r][0]],maxz[r]);
if(ch[r][1])maxz[r]=max(maxz[ch[r][1]],maxz[r]);
}
void rot(int r)
{if(r==0||tp[r]==0)return;
 pushdown(r);
 int y=fa[r],z=fa[y]; 
 bool flag=(ch[y][1]==r);
 ch[y][flag]=ch[r][!flag];
 if(ch[y][flag])fa[ch[y][flag]]=y;
 ch[r][!flag]=y;
 fa[y]=r;
 fa[r]=z;
 if(tp[y]==1)ch[z][ch[z][1]==y]=r;
 tp[r]=tp[y];
 rev[r]=rev[y];
 rev[y]=0;
 tp[y]=1;
 pushup(y); 
 //pushup(r);
}
void splay(int r)
{
    for(;tp[r]==1;rot(r))
    {
        int y=fa[r];
        if(y&&tp[y]==1)
        {
            int z=fa[y];
            rot(((ch[y][0]==r)==(ch[z][0]==y))?y:r);
        }
    }
    pushup(r);
    pushdown(r);
}
int access(int r)
{
    int last=0;
    while(r)
    {
        splay(r);
        if(ch[r][1])tp[ch[r][1]]=0;
        ch[r][1]=last;
        pushup(r);
        if(last)tp[last]=1;
        last=r;
        r=fa[r];
    }
    return last;
}
void beroot(int r)
{
    access(r);
    splay(r);
    rev[r]^=1;
    pushdown(r);
}
void link(int u,int v)
{
    beroot(u);
    fa[u]=v;
}
int querysum(int u,int v)
{
    beroot(u);
    access(v);
    splay(v);
    return sum[v];
}
int querymax(int u,int v)
{
    beroot(u);
    access(v);
    splay(v);
    return maxz[v];
}
int main()
{
    getint(n);
    int t1,t2;
    for(int i=1;i<n;i++)
    {
    getint(e[i].u),getint(e[i].v);
    
    }
    for(int i=1;i<=n;i++)
    getint(val[i]);
    for(int i=1;i<=n;i++)
    {
        sum[i]=maxz[i]=val[i];
    } 
    
    for(int i=1;i<n;i++)
    {
        link(e[i].u,e[i].v);
    }
    
    getint(q);
    for(int i=1;i<=q;i++)
    {
      scanf("%s",opt);
      getint(t1),getint(t2);
      if(opt[1]=='H')
      {
          val[t1]=t2;
          pushup(t1);
          access(t1);
          splay(t1);
      }
      else if(opt[1]=='M')
      {
          printf("%d
",querymax(t1,t2));
      }
      else if(opt[1]=='S')
      printf("%d
",querysum(t1,t2));
    
    }
    return 0; 
}
原文地址:https://www.cnblogs.com/hefenghhhh/p/5028860.html