zoukankan      html  css  js  c++  java
  • [ZJOI2008]树的统计

    题目描述

    一棵树上有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本身

    输入输出格式

    输入格式:

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

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

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    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
    
    输出样例#1: 复制
    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    

    说明

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

    模板水题

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N=30005;
      7 struct Node
      8 {
      9   int next,to;
     10 }edge[2*N];
     11 int cm[4*N],cs[4*N];
     12 int size[N],top[N],num,head[N],son[N],dfn[N],id[N],cnt,fa[N];
     13 int dep[N],w[N],n,q;
     14 char s[21];
     15 void add(int u,int v)
     16 {
     17   num++;
     18   edge[num].next=head[u];
     19   head[u]=num;
     20   edge[num].to=v;
     21 }
     22 void dfs1(int x,int pa)
     23 {int i;
     24   size[x]=1;
     25   for (i=head[x];i;i=edge[i].next)
     26     {
     27       int v=edge[i].to;
     28       if (v==pa) continue;
     29       dfs1(v,x);
     30       size[x]+=size[v];
     31       if (size[v]>size[son[x]]) son[x]=v;
     32     }
     33 }
     34 void dfs2(int x,int pa,int tp)
     35 {int i;
     36   dfn[x]=++cnt;
     37   id[cnt]=x;fa[x]=pa;
     38   top[x]=tp;dep[x]=dep[pa]+1;
     39   if (son[x])
     40     dfs2(son[x],x,tp);
     41   for (i=head[x];i;i=edge[i].next)
     42     {
     43       int v=edge[i].to;
     44       if (v==pa||v==son[x]) continue;
     45       dfs2(v,x,v);
     46     }
     47 }
     48 void pushup(int rt)
     49 {
     50   cm[rt]=max(cm[rt<<1],cm[rt<<1|1]);
     51   cs[rt]=cs[rt<<1]+cs[rt<<1|1];
     52 }
     53 void build(int rt,int l,int r)
     54 {
     55   if (l==r)
     56     {
     57       cm[rt]=w[id[l]];
     58       cs[rt]=w[id[l]];
     59       return;
     60     }
     61   int mid=(l+r)>>1;
     62   build(rt<<1,l,mid);
     63   build(rt<<1|1,mid+1,r);
     64   pushup(rt);
     65 }
     66 void update(int rt,int l,int r,int x,int k)
     67 {
     68   if (l==r)
     69     {
     70       cm[rt]=cs[rt]=k;
     71       return;
     72     }
     73   int mid=(l+r)>>1;
     74   if (x<=mid) update(rt<<1,l,mid,x,k);
     75   else update(rt<<1|1,mid+1,r,x,k);
     76   pushup(rt);
     77 }
     78 int query_max(int rt,int l,int r,int L,int R)
     79 {
     80   if (l>=L&&r<=R)
     81     {
     82       return cm[rt];
     83     }
     84   int mid=(l+r)>>1,s=-2e9;
     85   if (L<=mid) s=max(s,query_max(rt<<1,l,mid,L,R));
     86   if (R>mid) s=max(s,query_max(rt<<1|1,mid+1,r,L,R));
     87   pushup(rt);
     88   return s;
     89 }
     90 int query_sum(int rt,int l,int r,int L,int R)
     91 {
     92   if (l>=L&&r<=R)
     93     {
     94       return cs[rt];
     95     }
     96   int mid=(l+r)>>1,s=0;
     97   if (L<=mid) s=s+query_sum(rt<<1,l,mid,L,R);
     98   if (R>mid) s=s+query_sum(rt<<1|1,mid+1,r,L,R);
     99   pushup(rt);
    100   return s;
    101 }
    102 int get_max(int x,int y)
    103 {
    104   int as=-2e9;
    105   while (top[x]!=top[y])
    106     {
    107       if (dep[top[x]]<dep[top[y]]) swap(x,y);
    108       as=max(as,query_max(1,1,n,dfn[top[x]],dfn[x]));
    109       x=fa[top[x]];
    110     }
    111   if (dfn[x]>dfn[y]) swap(x,y);
    112   as=max(as,query_max(1,1,n,dfn[x],dfn[y]));
    113   return as;
    114 }
    115 int get_sum(int x,int y)
    116 {
    117   int as=0;
    118   while (top[x]!=top[y])
    119     {
    120       if (dep[top[x]]<dep[top[y]]) swap(x,y);
    121       as=as+query_sum(1,1,n,dfn[top[x]],dfn[x]);
    122       x=fa[top[x]];
    123     }
    124   if (dfn[x]>dfn[y]) swap(x,y);
    125   as=as+query_sum(1,1,n,dfn[x],dfn[y]);
    126   return as;
    127 }
    128 int main()
    129 {int i,u,v,x,y;
    130   cin>>n;
    131   for (i=1;i<=n-1;i++)
    132     {
    133       scanf("%d%d",&u,&v);
    134       add(u,v);add(v,u);
    135     }
    136   for (i=1;i<=n;i++)
    137       scanf("%d",&w[i]);
    138   dfs1(1,0);dfs2(1,0,1);
    139   build(1,1,n);
    140   cin>>q;
    141   while (q--)
    142     {
    143       scanf("%s",s);
    144       if (s[0]=='C')
    145     {
    146       scanf("%d%d",&x,&y);
    147       w[x]=y;
    148       update(1,1,n,dfn[x],y);
    149     }
    150       else if (s[1]=='M')
    151     {
    152       scanf("%d%d",&x,&y);
    153       printf("%d
    ",get_max(x,y));
    154     }
    155       else
    156     {
    157       scanf("%d%d",&x,&y);
    158       printf("%d
    ",get_sum(x,y));
    159     }
    160     }
    161 }
  • 相关阅读:
    线程唤醒
    以前、现在
    黑马程序员训练营基础测试
    流程图
    线程同步
    Thread联系
    Java线程
    Java中文件流笔记
    字符串习题
    匿名内部类
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8488778.html
Copyright © 2011-2022 走看看