zoukankan      html  css  js  c++  java
  • 1036: [ZJOI2008]树的统计Count (树链剖分)

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3401  Solved: 1418
    [Submit][Status]

    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

    入门题

      1 /* **********************************************
      2 Author      : kuangbin
      3 Created Time: 2013/8/12 21:58:47
      4 File Name   : F:2013ACM练习专题学习数链剖分树的统计Count.cpp
      5 *********************************************** */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 using namespace std;
     19 
     20 const int MAXN = 30010;
     21 struct Edge
     22 {
     23     int to,next;
     24 }edge[MAXN*2];
     25 int head[MAXN],tot;
     26 int top[MAXN]; //top[v] 表示v所在的重链的顶端节点
     27 int fa[MAXN]; //父亲节点
     28 int deep[MAXN];//深度
     29 int num[MAXN]; //num[v]表示以v为根的子树的节点数
     30 int p[MAXN]; //p[v]表示v在线段树中的位置
     31 int fp[MAXN];//和p数组相反
     32 int son[MAXN];//重儿子
     33 int pos;
     34 void init()
     35 {
     36     tot = 0;
     37     memset(head,-1,sizeof(head));
     38     pos = 0;
     39     memset(son,-1,sizeof(son));
     40 }
     41 void addedge(int u,int v)
     42 {
     43     edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++;
     44 }
     45 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son
     46 {
     47     deep[u] = d;
     48     fa[u] = pre;
     49     num[u] = 1;
     50     for(int i = head[u];i != -1;i = edge[i].next)
     51     {
     52         int v = edge[i].to;
     53         if(v != pre)
     54         {
     55             dfs1(v,u,d+1);
     56             num[u] += num[v];
     57             if(son[u] == -1 || num[v] > num[son[u]])
     58                 son[u] = v;
     59         }
     60     }
     61 }
     62 void getpos(int u,int sp)
     63 {
     64     top[u] = sp;
     65     p[u] = pos++;
     66     fp[p[u]] = u;
     67     if(son[u] == -1) return;
     68     getpos(son[u],sp);
     69     for(int i = head[u]; i != -1 ; i = edge[i].next)
     70     {
     71         int v = edge[i].to;
     72         if(v != son[u] && v != fa[u]) getpos(v,v);
     73     }
     74 }
     75 
     76 struct Node
     77 {
     78     int l,r;
     79     int sum;
     80     int Max;
     81 }segTree[MAXN*3];
     82 void push_up(int i)
     83 {
     84     segTree[i].sum = segTree[i<<1].sum + segTree[(i<<1)|1].sum;
     85     segTree[i].Max = max(segTree[i<<1].Max,segTree[(i<<1)|1].Max);
     86 } 
     87 int s[MAXN];
     88 void build(int i,int l,int r)
     89 {
     90     segTree[i].l = l;
     91     segTree[i].r = r;
     92     if(l == r)
     93     {
     94         segTree[i].sum = segTree[i].Max = s[fp[l]];
     95         return ;
     96     }
     97     int mid = (l + r)/2;
     98     build(i<<1,l,mid);
     99     build((i<<1)|1,mid+1,r);
    100     push_up(i);
    101 }
    102 void update(int i,int k,int val)//更新线段树的第k个值为val
    103 {
    104     if(segTree[i].l == k && segTree[i].r == k)
    105     {
    106         segTree[i].sum = segTree[i].Max = val;
    107         return;
    108     }
    109     int mid = (segTree[i].l + segTree[i].r)/2;
    110     if(k <= mid)update(i<<1,k,val);
    111     else update((i<<1)|1,k,val);
    112     push_up(i);
    113 }
    114 int queryMax(int i,int l,int r)//查询线段树[l,r]区间的最大值
    115 {
    116     if(segTree[i].l == l && segTree[i].r == r)
    117     {
    118         return segTree[i].Max;
    119     }
    120     int mid = (segTree[i].l + segTree[i].r)/2;
    121     if(r <= mid) return queryMax(i<<1,l,r);
    122     else if(l > mid)return queryMax((i<<1)|1,l,r);
    123     else return max(queryMax(i<<1,l,mid),queryMax((i<<1)|1,mid+1,r));
    124 }
    125 int querySum(int i,int l,int r) //查询线段树[l,r]区间的和
    126 {
    127     if(segTree[i].l == l && segTree[i].r == r)
    128         return segTree[i].sum;
    129     int mid = (segTree[i].l + segTree[i].r)/2;
    130     if(r <= mid)return querySum(i<<1,l,r);
    131     else if(l > mid)return querySum((i<<1)|1,l,r);
    132     else return querySum(i<<1,l,mid) + querySum((i<<1)|1,mid+1,r);
    133 }
    134 int findMax(int u,int v)//查询u->v路径上节点的最大权值
    135 {
    136     int f1 = top[u] , f2 = top[v];
    137     int tmp = -1000000000;
    138     while(f1 != f2)
    139     {
    140         if(deep[f1] < deep[f2])
    141         {
    142             swap(f1,f2);
    143             swap(u,v);
    144         }
    145         tmp = max(tmp,queryMax(1,p[f1],p[u]));
    146         u = fa[f1];
    147         f1 = top[u];
    148     }
    149     if(deep[u] > deep[v]) swap(u,v);
    150     return max(tmp,queryMax(1,p[u],p[v]));
    151 }
    152 int findSum(int u,int v) //查询u->v路径上节点的权值的和
    153 {
    154     int f1 = top[u], f2 = top[v];
    155     int tmp = 0;
    156     while(f1 != f2)
    157     {
    158         if(deep[f1] < deep[f2])
    159         {
    160             swap(f1,f2);
    161             swap(u,v);
    162         }
    163         tmp += querySum(1,p[f1],p[u]);
    164         u = fa[f1];
    165         f1 = top[u];
    166     }
    167     if(deep[u] > deep[v]) swap(u,v);
    168     return tmp + querySum(1,p[u],p[v]);
    169 }
    170 int main() 
    171 {
    172     //freopen("in.txt","r",stdin);
    173     //freopen("out.txt","w",stdout);
    174     int n;
    175     int q;
    176     char op[20];
    177     int u,v;
    178     while(scanf("%d",&n) == 1)
    179     {
    180         init();
    181         for(int i = 1;i < n;i++)
    182         {
    183             scanf("%d%d",&u,&v);
    184             addedge(u,v);
    185             addedge(v,u);
    186         }
    187         for(int i = 1;i <= n;i++)
    188             scanf("%d",&s[i]);
    189         dfs1(1,0,0);
    190         getpos(1,1);
    191         build(1,0,pos-1);
    192         scanf("%d",&q);
    193         while(q--)
    194         {
    195             scanf("%s%d%d",op,&u,&v);
    196             if(op[0] == 'C')
    197                 update(1,p[u],v);//修改单点的值
    198             else if(strcmp(op,"QMAX") == 0)
    199                 printf("%d
    ",findMax(u,v));//查询u->v路径上点权的最大值
    200             else printf("%d
    ",findSum(u,v));//查询路径上点权的和
    201         }
    202     }
    203     return 0;
    204 }
  • 相关阅读:
    less学习笔记(一)
    Angular.js学习笔记(三)
    备份域控制器升级为主域控制器
    MS SQL 2005 无法建立用户实例
    MS sql 无法进行事务日志备份
    安装设置IIS5.1
    问卷设计入门
    windows installer 应用变换时的错误.请验证指定的变换路径是否有
    【HDOJ6225】Little Boxes(Java)
    【HDOJ6222】Heron and His Triangle(Java,二分,递推)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3259083.html
Copyright © 2011-2022 走看看