• [ZJOI2008]树的统计Count


    题目描述 Description

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

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

    1. I.                    CHANGE u t : 把结点u的权值改为t
    2. II.                 QMAX u v: 询问从点u到点v的路径上的节点的最大权值
    3. III.               QSUM u v: 询问从点u到点v的路径上的节点的权值和

     

    注意:从点u到点v的路径上的节点包括u和v本身

    输入描述 Input Description

    输入文件的第一行为一个整数n,表示节点的个数。

           接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

           接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。

           接下来1行,为一个整数q,表示操作的总数。

    接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

    输出描述 Output Description

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

    样例输入 Sample Input

    4

    1 2

    2 3

    4 1

    4 2 1 3

    12

    QMAX 3 4

    QMAX 3 3

    QMAX 3 2

    QMAX 2 3

    QSUM 3 4

    QSUM 2 1

    CHANGE 1 5

    QMAX 3 4

    CHANGE 3 6

    QMAX 3 4

    QMAX 2 4

    QSUM 3 4

    样例输出 Sample Output

    4

    1

    2

    2

    10

    6

    5

    6

    5

    16

    数据范围及提示 Data Size & Hint

    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    代码实现:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define ls k*2
     4 #define rs k*2+1
     5 using namespace std;
     6 int n,m,l,hs,nl,lfs;
     7 int a,b,ans;
     8 int s[100010],h[100010];
     9 char ch[12];
    10 struct node{int k,f,d,sz,ws,p,t;}p[100010];
    11 struct nate{int s,n;}e[200020];
    12 struct tree{int l,r,s,b;}t[400040];
    13 void build(int k,int l,int r){
    14     t[k].l=l;t[k].r=r;
    15     if(l==r){t[k].s=t[k].b=s[++nl];return;}
    16     int mid=(l+r)>>1;
    17     build(ls,l,mid);
    18     build(rs,mid+1,r);
    19     t[k].s=t[ls].s+t[rs].s;
    20     t[k].b=max(t[ls].b,t[rs].b);
    21 }
    22 void change(int k,int l,int r,int v){
    23     if(t[k].l==l&&t[k].r==r){t[k].s=t[k].b=v;return;}
    24     int mid=(t[k].l+t[k].r)>>1;
    25     if(l<=mid) change(ls,l,min(r,mid),v);
    26     if(r>mid) change(rs,max(l,mid+1),r,v);
    27     t[k].s=t[ls].s+t[rs].s;
    28     t[k].b=max(t[ls].b,t[rs].b);
    29 }
    30 int query1(int k,int l,int r){
    31     if(t[k].l==l&&t[k].r==r) return t[k].s;
    32     int mid=(t[k].l+t[k].r)>>1,ans=0;
    33     if(l<=mid) ans+=query1(ls,l,min(r,mid));
    34     if(r>mid) ans+=query1(rs,max(l,mid+1),r);
    35     return ans;
    36 }
    37 int query2(int k,int l,int r){
    38     if(t[k].l==l&&t[k].r==r) return t[k].b;
    39     int mid=(t[k].l+t[k].r)>>1,ans=-30000;
    40     if(l<=mid) ans=max(ans,query2(ls,l,min(r,mid)));
    41     if(r>mid) ans=max(ans,query2(rs,max(l,mid+1),r));
    42     return ans;
    43 }
    44 inline void add(int x,int y){e[++hs]=(nate){y,h[x]};h[x]=hs;}
    45 void dfs1(int k,int f,int d){
    46     p[k].f=f;p[k].d=d;p[k].sz=1;
    47     for(int i=h[k];i;i=e[i].n)
    48     if(e[i].s!=f){
    49         dfs1(e[i].s,k,d+1);
    50         p[k].sz+=p[e[i].s].sz;
    51         if(p[e[i].s].sz>p[p[k].ws].sz) p[k].ws=e[i].s;
    52     }
    53 }
    54 void dfs2(int k){
    55     s[++l]=p[k].k;p[k].p=l;
    56     if(p[k].ws){
    57         p[p[k].ws].t=p[k].t;
    58         dfs2(p[k].ws);
    59     }
    60     for(int i=h[k];i;i=e[i].n)
    61     if(e[i].s!=p[k].ws&&e[i].s!=p[k].f){
    62         p[e[i].s].t=e[i].s;
    63         dfs2(e[i].s);
    64     }
    65 }
    66 int main(){
    67     scanf("%d",&n);
    68     for(int i=1;i<n;i++) scanf("%d%d",&a,&b),add(a,b),add(b,a);
    69     for(int i=1;i<=n;i++) scanf("%d",&p[i].k);
    70     dfs1(1,1,1);
    71     dfs2(1);
    72     build(1,1,l);
    73     scanf("%d",&m);
    74     while(m--){
    75         scanf("%s%d%d",ch,&a,&b);
    76         if(ch[3]=='N') change(1,p[a].p,p[a].p,b);
    77         if(ch[3]=='X'){
    78             ans=-30000;
    79             for(;p[a].t!=p[b].t;a=p[p[a].t].f){
    80                 if(p[p[a].t].p<p[p[b].t].p) swap(a,b);
    81                 ans=max(ans,query2(1,p[p[a].t].p,p[a].p));
    82             }
    83             if(p[a].p>p[b].p) swap(a,b);
    84             ans=max(ans,query2(1,p[a].p,p[b].p));
    85             printf("%d
    ",ans);
    86         }
    87         if(ch[3]=='M'){
    88             ans=0;
    89             for(;p[a].t!=p[b].t;a=p[p[a].t].f){
    90                 if(p[p[a].t].p<p[p[b].t].p) swap(a,b);
    91                 ans+=query1(1,p[p[a].t].p,p[a].p);
    92             }
    93             if(p[a].p>p[b].p) swap(a,b);
    94             ans+=query1(1,p[a].p,p[b].p);
    95             printf("%d
    ",ans);
    96         }
    97     }
    98     return 0;
    99 }

    题目来源:CODE[VS]

  • 相关阅读:
    Qt属性动画效果的实现QPropertyAnimation & 自定义属性Q_PROPERTY
    Qt实现鼠标拖拉窗口,并实现模拟鼠标拖拉窗口代码实例
    qt模拟鼠标左击下移动
    Qt新建线程
    Qt中子进程和父进程之间信号和槽通信
    vs2015打开Qt项目出现qt所有头文件都找不到
    vs2015运行Qt项目出现namespace "Ui" 没有成员“XXXClass”
    Opencv Mat类
    cv::cvtColor()的作用
    Delphi 系统[21]关键字和保留字 constructor、destructor、property
  • 原文地址:https://www.cnblogs.com/J-william/p/6383457.html
Copyright © 2020-2023  润新知