zoukankan      html  css  js  c++  java
  • P2590 [ZJOI2008]树的统计(LCT)

     P2590 [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本身

    输入输出格式

    输入格式:

    输入文件的第一行为一个整数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之间。

    code

    树链剖分1000ms左右,动态树4000ms多,不过动态树比树链剖分好写一点。

    树链剖分

      1 #include<cstdio>
      2 #include<algorithm>
      3  
      4 using namespace std;
      5  
      6 const int N = 50100;
      7  
      8 int val[N],fa[N],ch[N][2],rev[N],sum[N],mx[N],st[N],top;
      9 struct Edge{
     10     int to,nxt;
     11 }e[N<<1];
     12 int head[N],tot;
     13 
     14 inline void add_edge(int u,int v) {
     15     e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot;
     16 }
     17 void pushup(int x) {
     18     sum[x] = sum[ch[x][1]] + sum[ch[x][0]] + val[x];
     19     mx[x] = max(max(mx[ch[x][1]],mx[ch[x][0]]),val[x]);
     20 }
     21 void pushdown(int x) {
     22     int l = ch[x][0],r = ch[x][1];
     23     if (rev[x]) {
     24         rev[l] ^= 1;rev[r] ^= 1;
     25         swap(ch[x][0],ch[x][1]);
     26         rev[x] ^= 1;
     27     }
     28 }
     29 bool isroot(int x) {
     30     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
     31 }
     32 int son(int x) {
     33     return ch[fa[x]][1]==x;
     34 }
     35 void rotate(int x) {
     36     int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b];
     37     if (!isroot(y)) ch[z][c] = x;fa[x] = z;
     38     ch[x][!b] = y;fa[y] = x;
     39     ch[y][b] = a;if (a) fa[a] = y;
     40     pushup(y);pushup(x);
     41 }
     42 void splay(int x) {
     43     top = 0;st[++top] = x;
     44     for (int i=x; !isroot(i); i=fa[i]) st[++top] = fa[i];
     45     while (top) pushdown(st[top--]);
     46     while (!isroot(x)) {
     47         int y = fa[x];
     48         if (!isroot(y)) {
     49             if (son(x)==son(y)) rotate(y);
     50             else rotate(x);
     51         }
     52         rotate(x);
     53     }
     54 }
     55 void access(int x) {
     56     for (int t=0; x; t=x,x=fa[x]) {
     57         splay(x);ch[x][1] = t;pushup(x);
     58     }
     59 }
     60 void makeroot(int x) {
     61     access(x);
     62     splay(x);
     63     rev[x] ^= 1;
     64 }
     65 void update(int x,int y) {
     66     makeroot(x);val[x] = y;pushup(x);
     67 }
     68 int query_max(int x,int y) {
     69     makeroot(x);access(y);splay(y);
     70     return mx[y]; // - 
     71 }
     72 int query_sum(int x,int y) {
     73     makeroot(x);access(y);splay(y);
     74     return sum[y]; // -
     75 }
     76 void dfs(int u) {
     77     for (int i=head[u]; i; i=e[i].nxt) {
     78         int v = e[i].to;
     79         if (v==fa[u]) continue;
     80         fa[v] = u;
     81         dfs(v);
     82     }
     83 }
     84 int main() {
     85     int n,q,x,y;
     86     char opt[20];
     87     mx[0] = -1e9; // -
     88     scanf("%d",&n);
     89     for (int a,b,i=1; i<n; ++i) {
     90         scanf("%d%d",&a,&b);
     91         add_edge(a,b);add_edge(b,a);
     92     }
     93     for (int i=1; i<=n; ++i) scanf("%d",&val[i]);
     94     dfs(1);
     95     scanf("%d",&q);
     96     while (q--) {
     97         scanf("%s%d%d",opt,&x,&y);
     98         if (opt[1]=='H') update(x,y);
     99         else if (opt[1]=='M') printf("%d
    ",query_max(x,y));
    100         else printf("%d
    ",query_sum(x,y));
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    HDU1074 Doing Homework(状压dp)
    HDU1069 Monkey and Banana(dp)
    HDU1024 Max Sum Plus Plus(dp)
    codeforces 1288E. Messenger Simulator(树状数组)
    codeforces 1288D. Minimax Problem(二分)
    geotrellis使用(三十二)大量GeoTiff文件实时发布TMS服务
    geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务
    OpenStack(企业私有云)万里长征第六步——OpenStack网络及虚拟机存储位置
    geotrellis使用(三十)使用geotrellis读取PostGIS空间数据
    Docker Swarm——集群管理
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8150623.html
Copyright © 2011-2022 走看看