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 }
    ——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
  • 相关阅读:
    JavaScript对原始数据类型的拆装箱操作
    Javascript继承(原始写法,非es6 class)
    动态作用域与词法作用域
    自行车的保养
    探索JS引擎工作原理 (转)
    C语言提高 (7) 第七天 回调函数 预处理函数DEBUG 动态链接库
    C语言提高 (6) 第六天 文件(续) 链表的操作
    C语言提高 (5) 第五天 结构体,结构体对齐 文件
    C语言提高 (4) 第四天 数组与数组作为参数时的数组指针
    C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
  • 原文地址:https://www.cnblogs.com/Shy-key/p/7070772.html
Copyright © 2011-2022 走看看