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

    Description

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. 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”的操作,每行输出一个整数表示要求输出的结果。

    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

    HINT

     

    Source

     树剖的模版题
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define MAXN 30005
      6 using namespace std;
      7 int fa[MAXN],dep[MAXN],size[MAXN],gs[MAXN];
      8 int top[MAXN],tree[MAXN],pre[MAXN],tot;
      9 int first[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt;
     10 int n;
     11 int dat1[MAXN<<2],dat2[MAXN<<2],A[MAXN];
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0'||ch>'9'){if('-'==ch)f=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 void add(int x,int y){
     19     nxt[++cnt]=first[x];first[x]=cnt;to[cnt]=y;
     20     nxt[++cnt]=first[y];first[y]=cnt;to[cnt]=x;
     21 }
     22 void dfs1(int x){
     23     size[x]=1;
     24     for(int e=first[x];e;e=nxt[e]){
     25         int y=to[e];
     26         if(y==fa[x]){
     27             continue;
     28         }
     29         fa[y]=x;
     30         dep[y]=dep[x]+1;
     31         dfs1(y);
     32         size[x]+=size[y];
     33         if(size[y]>size[gs[x]]){
     34             gs[x]=y;
     35         }
     36     }
     37 }
     38 void dfs2(int x,int t){
     39     top[x]=t;
     40     tree[x]=(++tot);
     41     pre[tot]=x;
     42     if(!gs[x]){
     43         return;
     44     }
     45     dfs2(gs[x],t);
     46     for(int e=first[x];e;e=nxt[e]){
     47         int y=to[e];
     48         if(y==fa[x]||y==gs[x]){
     49             continue;
     50         }
     51         dfs2(y,y);
     52     }
     53 }
     54 void pushup(int k){
     55     dat1[k]=dat1[k<<1]+dat1[k<<1|1];
     56     dat2[k]=max(dat2[k<<1],dat2[k<<1|1]);
     57 }
     58 void build(int k,int L,int R){
     59     if(L+1==R){
     60         dat1[k]=dat2[k]=A[pre[L]];
     61         return;
     62     }
     63     build(k<<1,L,(L+R)>>1);
     64     build(k<<1|1,(L+R)>>1,R);
     65     pushup(k);
     66 }
     67 void init(){
     68     n=read();
     69     for(int i=1;i<n;i++){
     70         int x=read(),y=read();
     71         add(x,y);
     72     }
     73     for(int i=1;i<=n;i++){
     74         A[i]=read();
     75     }
     76     dfs1(1);
     77     dfs2(1,1);
     78     build(1,1,n+1);
     79 }
     80 void add(int a,int k,int L,int R,int x){
     81     if(L+1==R){
     82         dat1[k]=dat2[k]=x;
     83         return; 
     84     }
     85     int mid=((L+R)>>1);
     86     if(a<mid){
     87         add(a,k<<1,L,mid,x);
     88     }
     89     else{
     90         add(a,k<<1|1,mid,R,x);
     91     }
     92     pushup(k);
     93 }
     94 int query_sum(int a,int b,int k,int L,int R){
     95     if(b<=L||R<=a){
     96         return 0;
     97     }
     98     else if(a<=L&&R<=b){
     99         return dat1[k];
    100     }    
    101     else{
    102         int lc=query_sum(a,b,k<<1,L,(L+R)>>1);
    103         int rc=query_sum(a,b,k<<1|1,(L+R)>>1,R);
    104         return (lc+rc);
    105     }
    106 }
    107 int query_max(int a,int b,int k,int L,int R){
    108     if(b<=L||R<=a){
    109         return -1000000;
    110     }
    111     else if(a<=L&&R<=b){
    112         return dat2[k];
    113     }    
    114     else{
    115         int lc=query_max(a,b,k<<1,L,(L+R)>>1);
    116         int rc=query_max(a,b,k<<1|1,(L+R)>>1,R);
    117         return max(lc,rc);
    118     }
    119 }
    120 int tree_ask_sum(int x,int y){
    121     int f1=top[x],f2=top[y];
    122     if(dep[f1]<dep[f2]){
    123         swap(f1,f2),swap(x,y);
    124     }
    125     int ret=0;
    126     while(f1!=f2){
    127         ret+=query_sum(tree[f1],tree[x]+1,1,1,n+1);
    128         x=fa[f1],f1=top[x];
    129         if(dep[f1]<dep[f2]){
    130             swap(f1,f2),swap(x,y);
    131         }
    132     }
    133     if(dep[x]>dep[y]){
    134         swap(x,y);
    135     }
    136     ret+=query_sum(tree[x],tree[y]+1,1,1,n+1);
    137     return ret;
    138 }
    139 int tree_ask_max(int x,int y){
    140     int f1=top[x],f2=top[y];
    141     if(dep[f1]<dep[f2]){
    142         swap(f1,f2),swap(x,y);
    143     }
    144     int ret=-1000000;
    145     while(f1!=f2){
    146         ret=max(ret,query_max(tree[f1],tree[x]+1,1,1,n+1));
    147         x=fa[f1],f1=top[x];
    148         if(dep[f1]<dep[f2]){
    149             swap(f1,f2),swap(x,y);
    150         }
    151     }
    152     if(dep[x]>dep[y]){
    153         swap(x,y);
    154     }
    155     ret=max(ret,query_max(tree[x],tree[y]+1,1,1,n+1));
    156     return ret;
    157 }
    158 void solve(){
    159     int T=read();
    160     for(int i=1;i<=T;i++){
    161         char ch[10];
    162         scanf("%s",ch);
    163         int x=read(),y=read();
    164         if('M'==ch[1]){
    165             printf("%d
    ",tree_ask_max(x,y));
    166         }
    167         else if('S'==ch[1]){
    168             printf("%d
    ",tree_ask_sum(x,y));
    169         }
    170         else{
    171             add(tree[x],1,1,n+1,y);
    172         }
    173     }
    174 }
    175 int main()
    176 {
    177 //    freopen("data.in","r",stdin);
    178     init();
    179     solve();
    180     return 0;
    181 }
  • 相关阅读:
    单片机基础
    EM310_AT收到的短信分析
    [原]改动CImage以实现以指定的质量保存Jpeg图像
    [原创]巧用DOS命令改子目录中的文件名
    二个月零七天,我女儿会翻身了
    [原]用正则得到HTML中所有的图片路径
    新文章:把程序放在相册中
    [原]用三行代码实现对音量的控制,实现增大,减小,静音
    BIOS中隐藏Telnet后门
    CoolChm 注册机的编写
  • 原文地址:https://www.cnblogs.com/w-h-h/p/7820188.html
Copyright © 2011-2022 走看看