zoukankan      html  css  js  c++  java
  • BZOJ1036 [ZJOI2008] 树的统计Count

    Description

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. 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”的操作,每行输出一个整数表示要求输出的结果。 

    经典的树链剖分,用线段树维护即可。

    只是发现以前写的时候没有开博客,补一下题解。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <queue>
      6 #include <climits>
      7 #define rep(i,l,r) for(int i=l; i<=r; i++)
      8 #define clr(x,y) memset(x,y,sizeof(x))
      9 #define travel(x) for(int i=last[x]; i; i=edge[i].pre)
     10 typedef long long ll;
     11 using namespace std;
     12 const int INF = 0x7fffffff;
     13 const int maxn = 30010;
     14 struct Edge{
     15     int pre,to;
     16 }edge[maxn<<1];
     17 struct segnode{
     18     int l,r,mx,sum;
     19 }tree[maxn<<2];
     20 int n,m,x,y,segnum=0,tot=0,depth[maxn],last[maxn],v[maxn],size[maxn],pos[maxn],belong[maxn],fa[maxn];
     21 char c[6];
     22 bool vis[maxn];
     23 inline int read(){
     24     int ans = 0, f = 1;
     25     char c = getchar();
     26     while (!isdigit(c)){
     27         if (c == '-') f = -1;
     28         c = getchar();
     29     }
     30     while (isdigit(c)){
     31         ans = ans * 10 + c - '0';
     32         c = getchar();
     33     }
     34     return ans * f;
     35 }
     36 inline void addedge(int x,int y){
     37     edge[++tot].pre = last[x];
     38     edge[tot].to = y;
     39     last[x] = tot;
     40 }
     41 void dfs(int x){
     42     vis[x] = 1; size[x] = 1;
     43     travel(x){
     44         if (!vis[edge[i].to]){
     45             depth[edge[i].to] = depth[x] + 1;
     46             fa[edge[i].to] = x;
     47             dfs(edge[i].to);
     48             size[x] += size[edge[i].to];
     49         }
     50     }
     51 }
     52 void dfs2(int x,int chain){
     53     int k = 0; pos[x] = ++segnum;
     54     belong[x] = chain;
     55     travel(x){
     56         if (depth[edge[i].to] > depth[x] && size[edge[i].to] > size[k])
     57         k = edge[i].to;
     58     }
     59     if (!k) return;
     60     dfs2(k,chain);
     61     travel(x){
     62         if (depth[edge[i].to] > depth[x] && k != edge[i].to)
     63         dfs2(edge[i].to,edge[i].to);
     64     }
     65 }
     66 void build(int u,int v,int w){
     67     tree[w].l = u;
     68     tree[w].r = v;
     69     if (u == v) return;
     70     build(u,(u+v)>>1,w<<1);
     71     build(((u+v)>>1)+1,v,w<<1|1);
     72 }
     73 int querysum(int u,int v,int w){
     74     if (u == tree[w].l && v == tree[w].r) return tree[w].sum;
     75     if (v <= tree[w<<1].r) return querysum(u,v,w<<1);
     76     if (u > tree[w<<1].r) return querysum(u,v,w<<1|1);
     77     return querysum(u,tree[w<<1].r,w<<1) + querysum(tree[w<<1|1].l,v,w<<1|1);
     78 }
     79 int querymx(int u,int v,int w){
     80     if (u == tree[w].l && v == tree[w].r) return tree[w].mx;
     81     if (v <= tree[w<<1].r) return querymx(u,v,w<<1);
     82     if (u > tree[w<<1].r) return querymx(u,v,w<<1|1);
     83     return max(querymx(u,tree[w<<1].r,w<<1), querymx(tree[w<<1|1].l,v,w<<1|1));
     84 }
     85 void update(int u,int w,int z){
     86     if (tree[w].l == tree[w].r){
     87         tree[w].sum = tree[w].mx = z;
     88         return;
     89     }
     90     int mid = (tree[w].l + tree[w].r) >> 1;
     91     if (u <= mid) update(u,w<<1,z);
     92     else update(u,w<<1|1,z);
     93     tree[w].sum = tree[w<<1].sum + tree[w<<1|1].sum;
     94     tree[w].mx = max(tree[w<<1].mx, tree[w<<1|1].mx);
     95 }
     96 int solvesum(int x,int y){
     97     int res = 0;
     98     while (belong[x] != belong[y]){
     99         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
    100         res += querysum(pos[belong[x]],pos[x],1);
    101         x = fa[belong[x]];
    102     }
    103     if (depth[x] < depth[y]) swap(x,y);
    104     res += querysum(pos[y],pos[x],1);
    105     return res;
    106 }
    107 int solvemx(int x,int y){
    108     int res = 0 - INF;
    109     while (belong[x] != belong[y]){
    110         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
    111         res = max(res,querymx(pos[belong[x]],pos[x],1));
    112         x = fa[belong[x]];
    113     }
    114     if (depth[x] < depth[y]) swap(x,y);
    115     res = max(res,querymx(pos[y],pos[x],1));
    116     return res;
    117 }
    118 int main(){
    119     n = read();
    120     rep(i,1,n-1){
    121         x = read(); y = read();
    122         addedge(x,y); addedge(y,x);
    123     }
    124     rep(i,1,n) v[i] = read();
    125     depth[1] = 0; dfs(1);
    126     dfs2(1,1);
    127     build(1,n,1);
    128     rep(i,1,n) update(pos[i],1,v[i]);
    129     m = read();
    130     rep(i,1,m){
    131         scanf("%s",c); x = read(); y = read();
    132         if (c[1] == 'M'){
    133             printf("%d
    ",solvemx(x,y));
    134         }
    135         else if (c[1] == 'S'){
    136             printf("%d
    ",solvesum(x,y));
    137         }
    138         else{
    139             v[x] = y;
    140             update(pos[x],1,y);
    141         }
    142     }
    143     return 0;
    144 }
    View Code
  • 相关阅读:
    九月二十日
    九月十九日
    九月十八日
    九月十七日
    九月十六日
    大三第一周学习后的感悟及本学期计划
    阅读笔记09梦断代码
    阅读笔记08-梦断代码
    对搜狗现如今的用法进行评述
    寻找水王
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1036.html
Copyright © 2011-2022 走看看