• [BZOJ] 1036: [ZJOI2008]树的统计Count


    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 18843  Solved: 7689
    [Submit][Status][Discuss]

    Description

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

    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

    Analysis

    树链剖分裸题!

    在此推荐 ACdreamer的树链剖分原理 !

    =w=

    树链剖分可以用百度到的一张图解释

    那么显然树链剖分还有第三个性质(主要是帮助理解的)

        “ 每一个点都在重链上 ”

    (其实有点废话,不过我一直对树剖有些相关误解)

    那么具体实现的时候,我们通过魔改他们的DFS序(优先遍历同一条重链上的子节点),然后把新版DFS序塞进线段树

    这样重链就都头尾相接了 =w=

    这里不对树剖做出详细的讲解(反正前人之述备矣而且还有ACdreamer大大的解释)

    只是一些零散的注释

    如果明明敲起来很顺又不觉得有什么问题

    看看你的函数有没有返回答案= =

    (本蒟蒻忘记返回值结果挂了)

    关于如何跳链 :

    操作的时候优先操作重链链头深度更深的

    也就是不停地操作深链然后一步步跳到同一条链上

    Code

      1 #include<cstdio>
      2 #include<iostream>
      3 #define maxn 1000000
      4 #define lc (rt<<1)
      5 #define rc (rt<<1|1)
      6 #define mid ((L+R)/2)
      7 using namespace std;
      8 
      9 const int inf = 1e9;
     10 
     11 int arr[maxn],siz[maxn],fa[maxn],depth[maxn],son[maxn],top[maxn],tid[maxn],TIM;
     12 int back[maxn],n,q;
     13 
     14 struct edge{
     15     int from,v;
     16 }e[maxn];
     17 int tot,first[maxn];
     18 void insert(int u,int v){ tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot; }
     19 
     20 struct node{
     21     int sum,maxx,lazy;
     22 }Tree[maxn];
     23 
     24 void maintain(int rt){ 
     25     Tree[rt].sum = Tree[lc].sum+Tree[rc].sum; 
     26     Tree[rt].maxx = max(Tree[lc].maxx,Tree[rc].maxx);
     27 }
     28 
     29 void pushdown(int rt,int L,int R){
     30     if(Tree[rt].lazy == -inf) return;
     31     Tree[lc].lazy = Tree[rt].lazy;
     32     Tree[rc].lazy = Tree[rt].lazy;
     33     Tree[rt].lazy = -inf;
     34     Tree[lc].sum = Tree[rt].lazy*(mid-L+1);
     35     Tree[lc].maxx = Tree[rt].lazy;
     36     Tree[rc].sum = Tree[rt].lazy*(R-mid);
     37     Tree[rc].maxx = Tree[rt].lazy;
     38 }
     39 
     40 void build(int rt,int L,int R){
     41     Tree[rt].lazy = -inf;
     42     if(L == R){
     43         Tree[rt].sum = arr[L];
     44         Tree[rt].maxx = arr[L];
     45     }else{
     46         build(lc,L,mid);
     47         build(rc,mid+1,R);
     48         
     49         maintain(rt);
     50     }
     51 }
     52 
     53 void modify(int rt,int L,int R,int qL,int qR,int val){
     54     pushdown(rt,L,R);
     55     if(qL <= L && R <= qR){
     56         Tree[rt].lazy = val;
     57         Tree[rt].sum = val*(R-L+1);
     58         Tree[rt].maxx = val;
     59     }else{
     60         if(qL <= mid) modify(lc,L,mid,qL,qR,val);
     61         if(qR > mid) modify(rc,mid+1,R,qL,qR,val);
     62         
     63         maintain(rt);
     64     }
     65 }
     66 
     67 int max_query(int rt,int L,int R,int qL,int qR){
     68     pushdown(rt,L,R);
     69     if(qL <= L && R <= qR) return Tree[rt].maxx;
     70     else{
     71         int ans = -inf;
     72         if(qL <= mid) ans = max(ans,max_query(lc,L,mid,qL,qR));
     73         if(qR > mid) ans = max(ans,max_query(rc,mid+1,R,qL,qR));
     74         return ans;
     75     }
     76 }
     77 
     78 int sum_query(int rt,int L,int R,int qL,int qR){
     79     pushdown(rt,L,R);
     80     if(qL <= L && R <= qR) return Tree[rt].sum;
     81     else{
     82         int ans = 0;
     83         if(qL <= mid) ans += sum_query(lc,L,mid,qL,qR);
     84         if(qR > mid) ans += sum_query(rc,mid+1,R,qL,qR);
     85         return ans;
     86     }
     87 }
     88 
     89 void dfs(int now){
     90     siz[now] = 1;
     91     for(int i = first[now];i;i = e[i].from){
     92         int v = e[i].v;
     93         if(v != fa[now]){
     94             fa[v] = now;
     95             depth[v] = depth[now]+1;
     96             dfs(v);
     97             siz[now] += siz[v];
     98             if(!son[now] || siz[v] > siz[son[now]])
     99                 son[now] = v;
    100         }
    101     }
    102 }
    103 
    104 void dfs2(int now,int upper){
    105     top[now] = upper;
    106     tid[now] = ++TIM;
    107     back[TIM] = now;
    108     if(!son[now]) return;
    109     dfs2(son[now],upper);
    110     for(int i = first[now];i;i = e[i].from){
    111         int v = e[i].v;
    112         if(v != fa[now] && v != son[now])
    113             dfs2(v,v);
    114     }
    115 }
    116 
    117 void CHANGE(int u,int val){
    118     modify(1,1,n,tid[u],tid[u],val);
    119 }
    120 
    121 int QMAX(int u,int v){
    122     if(depth[top[u]] > depth[top[v]]) swap(u,v);
    123     int ans = -inf;
    124     while(top[u] != top[v]){
    125         ans = max(max_query(1,1,n,tid[top[v]],tid[v]),ans);
    126         v = fa[top[v]];
    127         if(depth[top[u]] > depth[top[v]]) swap(u,v);
    128     }if(depth[u] > depth[v]) swap(u,v);
    129     ans = max(ans,max_query(1,1,n,tid[u],tid[v]));
    130     return ans;
    131 }
    132 
    133 int QSUM(int u,int v){
    134     if(depth[top[u]] > depth[top[v]]) swap(u,v);
    135     int ans = 0;
    136     while(top[u] != top[v]){
    137         ans += sum_query(1,1,n,tid[top[v]],tid[v]);
    138         v = fa[top[v]];
    139         if(depth[top[u]] > depth[top[v]]) swap(u,v);
    140     }if(depth[u] > depth[v]) swap(u,v);
    141     ans += sum_query(1,1,n,tid[u],tid[v]);
    142     return ans;
    143 }
    144 
    145 int main(){
    146     scanf("%d",&n);
    147     for(int i = 1;i < n;i++){
    148         int x,y; scanf("%d%d",&x,&y);
    149         insert(x,y); insert(y,x);
    150     }depth[1] = 1; dfs(1); dfs2(1,1);
    151     
    152     for(int i = 1;i <= n;i++)
    153         scanf("%d",&arr[tid[i]]);
    154     build(1,1,n);
    155         
    156     scanf("%d",&q);
    157     while(q--){
    158         char str[10];
    159         scanf("%s",str); int a,b;
    160         switch(str[1]){
    161             case 'M': //QMAX
    162                 scanf("%d%d",&a,&b);
    163                 printf("%d
    ",QMAX(a,b));
    164                 break;
    165             case 'S': //QSUM
    166                 scanf("%d%d",&a,&b);
    167                 printf("%d
    ",QSUM(a,b));
    168                 break;
    169             case 'H': //CHANGE
    170                 scanf("%d%d",&a,&b);
    171                 CHANGE(a,b);
    172                 break;
    173         }
    174     }
    175     
    176     return 0;
    177 }
    =w=美滋滋
  • 相关阅读:
    Axure 实现数字自动加键功能(点击“+”数字加1,点击“-”数字减1)
    Axure 实现批量的勾选和反选
    传说中的AutoCAD公司
    Autodesk 最新开发技术研讨会-北京-上海-武汉-成都-西安-PPT下载
    发布App,赢iPad mini + 美金100$
    无插件的大模型浏览器Autodesk Viewer开发培训-武汉-2014年8月28日 9:00 – 12:00
    为Autodesk Viewer添加自定义工具条的更好方法
    为Autodesk Viewer添加自定义工具条
    Autodesk 最新开发技术研讨会 -8月22日-Autodesk北京办公室
    请保护我们的地球
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7643104.html
Copyright © 2020-2023  润新知