zoukankan      html  css  js  c++  java
  • bzoj1036 [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本身

    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”的操作,每行输出一个整数表示要求输出的结果。

    树剖模板。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cmath>
      5 #include<cstring>
      6 using namespace std;
      7 
      8 const int INF=1e9+7,NN=30007,MM=1e5+7;
      9 
     10 int n,m,sz;
     11 int a[NN],deep[NN],size[NN],fa[NN],pos[NN],bl[NN];
     12 int cnt,head[NN],next[MM],rea[MM];
     13 struct Node
     14 {
     15     int l,r,mx,sum;
     16 }tree[MM];
     17 
     18 void add(int u,int v)
     19 {
     20     cnt++;
     21     next[cnt]=head[u];
     22     head[u]=cnt;
     23     rea[cnt]=v;
     24 }
     25 void dfs_init(int x)
     26 {
     27     size[x]=1;
     28     for (int i=head[x];i!=-1;i=next[i])
     29     {
     30         int v=rea[i];
     31         if (v==fa[x]) continue;
     32         deep[v]=deep[x]+1;
     33         fa[v]=x;
     34         dfs_init(v);
     35         size[x]+=size[v];
     36     }
     37 }
     38 void dfs_make(int x,int chain)//chain表示重链首的编号 
     39 {
     40     int k=0;//找重链 
     41     sz++;
     42     pos[x]=sz;//分配编号;
     43     bl[x]=chain;
     44     for (int i=head[x];i!=-1;i=next[i])
     45     {
     46         int v=rea[i];
     47         if (deep[v]>deep[x]&&size[v]>size[k]) k=v;
     48     }
     49     if (k==0) return;
     50     dfs_make(k,chain);
     51     for (int i=head[x];i!=-1;i=next[i])
     52     {
     53         int v=rea[i];
     54         if (deep[v]>deep[x]&&k!=v) dfs_make(v,v);
     55     }
     56 }
     57 void build(int k,int l,int r)
     58 {
     59     tree[k].l=l,tree[k].r=r;
     60     if (l==r) return;
     61     int mid=(l+r)>>1;
     62     build(k<<1,l,mid),build((k<<1)+1,mid+1,r); 
     63 }
     64 void change(int k,int x,int y)
     65 {
     66     int l=tree[k].l,r=tree[k].r,mid=(l+r)>>1;
     67     if (l==r){tree[k].sum=tree[k].mx=y;return;}
     68     if (x<=mid) change(k<<1,x,y);
     69     else change(k<<1|1,x,y);
     70     tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
     71     tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
     72 }
     73 int query_sum(int k,int x,int y)
     74 {
     75     int l=tree[k].l,r=tree[k].r,mid=(l+r)>>1;
     76     if (l==x&&r==y) return tree[k].sum;
     77     if (y<=mid) return query_sum(k<<1,x,y);
     78     else if (x>mid) return query_sum(k<<1|1,x,y);
     79     else return query_sum(k<<1,x,mid)+query_sum(k<<1|1,mid+1,y);
     80 }
     81 int query_max(int k,int x,int y)
     82 {
     83     int l=tree[k].l,r=tree[k].r,mid=(l+r)>>1;
     84     if (l==x&&y==r) return tree[k].mx;
     85     if (y<=mid) return query_max(k<<1,x,y);
     86     else if (x>mid) return query_max(k<<1|1,x,y);
     87     else return max(query_max(k<<1,x,mid),query_max(k<<1|1,mid+1,y));
     88 }
     89 int solve_sum(int x,int y)
     90 {
     91     int sum=0;
     92     while (bl[x]!=bl[y])//表示标记不同
     93     {
     94         if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
     95         sum+=query_sum(1,pos[bl[x]],pos[x]);
     96         x=fa[bl[x]]; //跳完整条重链。 
     97     }
     98     if (pos[x]>pos[y]) swap(x,y);
     99     sum+=query_sum(1,pos[x],pos[y]);
    100     return sum;
    101 }
    102 int solve_max(int x,int y)
    103 {
    104     int mx=-INF;
    105     while (bl[x]!=bl[y])
    106     {
    107         if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
    108         mx=max(mx,query_max(1,pos[bl[x]],pos[x]));
    109         x=fa[bl[x]];
    110     }
    111     if (pos[x]>pos[y]) swap(x,y);
    112     mx=max(mx,query_max(1,pos[x],pos[y]));
    113     return mx;
    114 }
    115 int main()
    116 {
    117     memset(head,-1,sizeof(head));
    118     scanf("%d",&n);
    119     for (int i=1;i<n;i++)
    120     {
    121         int x,y;
    122         scanf("%d%d",&x,&y);
    123         add(x,y),add(y,x);
    124     }
    125     for (int i=1;i<=n;i++)
    126         scanf("%d",&a[i]);
    127     dfs_init(1);
    128     dfs_make(1,1);    
    129     build(1,1,n);//建树。
    130     for (int i=1;i<=n;i++)
    131         change(1,pos[i],a[i]);
    132     scanf("%d",&m);
    133     char c[10];
    134     for (int i=1;i<=m;i++)
    135     {
    136         int x,y;
    137         scanf("%s%d%d",c,&x,&y);
    138         if (c[0]=='C')
    139         {
    140             a[x]=y;
    141             change(1,pos[x],y);
    142         }
    143         else
    144         {
    145             if (c[1]=='M') printf("%d
    ",solve_max(x,y));
    146             else printf("%d
    ",solve_sum(x,y));
    147         }
    148     }
    149 }
  • 相关阅读:
    Codeforces 691A Fashion in Berland
    HDU 5741 Helter Skelter
    HDU 5735 Born Slippy
    HDU 5739 Fantasia
    HDU 5738 Eureka
    HDU 5734 Acperience
    HDU 5742 It's All In The Mind
    POJ Euro Efficiency 1252
    AtCoder Beginner Contest 067 C
    AtCoder Beginner Contest 067 D
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7500242.html
Copyright © 2011-2022 走看看