zoukankan      html  css  js  c++  java
  • 洛谷——P2590 [ZJOI2008]树的统计

    https://www.luogu.org/problem/show?pid=2590#sub

    题目描述

    一棵树上有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 <algorithm>
      2 #include <string>
      3 #include <cstdio>
      4 
      5 using namespace std;
      6 
      7 const int N(30000+15);
      8 int n,u,v,val[N],q;
      9 char op[10];
     10 
     11 int head[N],sumedge;
     12 struct Edge
     13 {
     14     int u,v,next;
     15     Edge(int u=0,int v=0,int next=0):
     16         u(u),v(v),next(next){}
     17 }edge[N<<1];
     18 void ins(int u,int v)
     19 {
     20     edge[++sumedge]=Edge(u,v,head[u]);
     21     head[u]=sumedge;
     22 }
     23 
     24 int cnt,id[N],dfn[N],size[N],son[N],top[N],dad[N],deep[N];
     25 void DFS(int u,int father,int deepth)
     26 {
     27     deep[u]=deepth;
     28     dad[u]=father;
     29     size[u]=1;
     30     son[u]=0;
     31     for(int i=head[u];i;i=edge[i].next)
     32     {
     33         int to=edge[i].v;
     34         if(dad[u]==to) continue;
     35         DFS(to,u,deepth+1);    size[u]+=size[to];
     36         if(!son[u]||size[son[u]]<size[to]) son[u]=to;
     37     }
     38 }
     39 void DFS_(int u,int Top)
     40 {
     41     top[u]=Top;
     42     id[u]=++cnt;
     43     dfn[cnt]=u;
     44     if(son[u]) DFS_(son[u],Top);
     45     for(int i=head[u];i;i=edge[i].next)
     46     {
     47         int to=edge[i].v;
     48         if(to!=dad[u]&&to!=son[u]) DFS_(to,to);
     49     }
     50 }
     51 
     52 struct Tree
     53 {
     54     int l,r,mid,sumval,maxval;
     55 }tree[N<<2];
     56 void Tree_up(int now)
     57 {
     58     tree[now].sumval=tree[now<<1].sumval+tree[now<<1|1].sumval;
     59     tree[now].maxval=max(tree[now<<1].maxval,tree[now<<1|1].maxval);
     60 }
     61 void Tree_build(int now,int l,int r)
     62 {
     63     tree[now].l=l;tree[now].r=r;
     64     if(l==r)
     65     {
     66         tree[now].maxval=val[dfn[l]];
     67         tree[now].sumval=val[dfn[l]];
     68         return ;
     69     }
     70     tree[now].mid=l+r>>1;
     71     Tree_build(now<<1,l,tree[now].mid);
     72     Tree_build(now<<1|1,tree[now].mid+1,r);
     73     Tree_up(now);
     74 }
     75 void Tree_change(int now,int to,int x)
     76 {
     77     if(tree[now].l==tree[now].r)
     78     {
     79         tree[now].maxval=x;
     80         tree[now].sumval=x;
     81         return ;
     82     }
     83     if(tree[now].mid>=to) Tree_change(now<<1,to,x);
     84     else if(tree[now].mid<to) Tree_change(now<<1|1,to,x);
     85     Tree_up(now);
     86 }
     87 int Tree_querymax(int now,int l,int r)
     88 {
     89     if(tree[now].l==l&&tree[now].r==r) return tree[now].maxval;
     90     if(tree[now].mid>=r) return Tree_querymax(now<<1,l,r);
     91     else if(tree[now].mid<l) return Tree_querymax(now<<1|1,l,r);
     92     else return max(Tree_querymax(now<<1,l,tree[now].mid),Tree_querymax(now<<1|1,tree[now].mid+1,r));
     93 }
     94 int Tree_querysum(int now,int l,int r)
     95 {
     96     if(tree[now].l==l&&tree[now].r==r) return tree[now].sumval;
     97     if(tree[now].mid>=r) return Tree_querysum(now<<1,l,r);
     98     else if(tree[now].mid<l) return Tree_querysum(now<<1|1,l,r);
     99     else return Tree_querysum(now<<1,l,tree[now].mid)+Tree_querysum(now<<1|1,tree[now].mid+1,r);
    100 }
    101 
    102 int List_querymax(int x,int y)
    103 {
    104     int ret=-1e9;
    105     for(;top[x]!=top[y];x=dad[top[x]])
    106     {
    107         if(deep[top[x]]<deep[top[y]]) swap(x,y);
    108         ret=max(ret,Tree_querymax(1,id[top[x]],id[x]));
    109     }
    110     if(id[x]>id[y]) swap(x,y);
    111     ret=max(ret,Tree_querymax(1,id[x],id[y]));
    112     return ret;
    113 }
    114 int List_querysum(int x,int y)
    115 {
    116     int ret=0;
    117     for(;top[x]!=top[y];x=dad[top[x]])
    118     {
    119         if(deep[top[x]]<deep[top[y]]) swap(x,y);
    120         ret+=Tree_querysum(1,id[top[x]],id[x]);
    121     }
    122     if(id[x]>id[y]) swap(x,y);
    123     ret+=Tree_querysum(1,id[x],id[y]);
    124     return ret;
    125 }
    126 
    127 int main()
    128 {
    129     scanf("%d",&n);
    130     for(int i=1;i<n;i++)
    131         scanf("%d%d",&u,&v),ins(u,v),ins(v,u);
    132     for(int i=1;i<=n;i++) scanf("%d",val+i);
    133     DFS(1,0,1);DFS_(1,1);
    134     Tree_build(1,1,n);
    135     scanf("%d",&q);
    136     for(;q--;)
    137     {
    138         scanf("%s%d%d",op,&u,&v);
    139         if(op[0]=='C') Tree_change(1,id[u],v);
    140         else if(op[1]=='M') printf("%d
    ",List_querymax(u,v));
    141         else printf("%d
    ",List_querysum(u,v));
    142     }
    143     return 0;
    144 }
    ——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
  • 相关阅读:
    理解钩子Hook以及在Thinkphp下利用钩子使用行为扩展
    ThinkPHP 分页类的使用及退出功能的实现
    ThinkPHP登录功能代码
    thinkphp遗留问题
    ThinkPHP随笔
    ThinkPhp循环出数据库中的内容并输出到模板
    thinkphp常用Config.php配置项
    thinkphp笔记
    PHP面向对象学习七 总结
    Trie树
  • 原文地址:https://www.cnblogs.com/Shy-key/p/7070772.html
Copyright © 2011-2022 走看看