• 树的统计


    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; 
    }
  • 相关阅读:
    Qt简介以及如何配置Qt使用VS2010进行开发
    QT里重定向另外一个控制台程序的输出
    windows下制作PHP扩展
    20款Notepad++插件下载和介绍
    音频编码协议介绍
    用 PHP 读取文件的正确方法
    QT进程间通信
    关于YUV色彩空间
    解析xml 四种
    System.getProperty
  • 原文地址:https://www.cnblogs.com/hefenghhhh/p/5028860.html
Copyright © 2020-2023  润新知