• 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 }
  • 相关阅读:
    【20220502】连岳摘抄
    【20220423】家是孩子最重要的教育场所
    【20220425】连岳摘抄
    【20220430】连岳摘抄
    【20220427】二宝让我们省吃俭用
    【20220503】连岳摘抄
    工作感受月记202205月
    Appium实现百词斩
    Appium自动微信读书打卡
    删除ssh 连接缓存
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7500242.html
Copyright © 2020-2023  润新知