• bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)


    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 10677  Solved: 4313
    [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

    【思路】

           树链剖分,线段树

           线段树:区间查询max sum ,单点操作 set。

           注意一下负数就行了=-=。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      7 using namespace std;
      8 
      9 const int N = 50000+10;
     10 const int INF = 1e9;
     11 
     12 struct Node {
     13     int mx,sum;
     14     Node() {mx=-INF,sum=0;}
     15 }T[N<<1];
     16 
     17 int n,q,z;
     18 char s[20];
     19 vector<int> g[N];
     20 //INIT
     21 int top[N],son[N],dep[N],fa[N],siz[N],w[N];
     22 void dfs1(int u) {
     23     son[u]=0; siz[u]=1;
     24     for(int i=0;i<g[u].size();i++) {
     25         int v=g[u][i];
     26         if(v!=fa[u]) {
     27             fa[v]=u , dep[v]=dep[u]+1;
     28             dfs1(v);
     29             siz[u]+=siz[v];
     30             if(siz[v]>siz[son[u]]) son[u]=v;
     31         }
     32     }
     33 }
     34 void dfs2(int u,int tp) {
     35     top[u]=tp; w[u]=++z;
     36     if(son[u]) dfs2(son[u],tp);
     37     for(int i=0;i<g[u].size();i++) {
     38         int v=g[u][i];
     39         if(v!=fa[u] && v!=son[u]) dfs2(v,v);
     40     }
     41 }
     42 //SEGMENT TREE
     43 void update(int u,int L,int R,int r,int x) {
     44     if(L==R) T[u].mx=T[u].sum=x;
     45     else {
     46         int M=(L+R)>>1,lc=u<<1,rc=lc|1;
     47         if(r<=M) update(lc,L,M,r,x);
     48         else update(rc,M+1,R,r,x);
     49         T[u].mx=max(T[lc].mx,T[rc].mx);
     50         T[u].sum=T[lc].sum+T[rc].sum;
     51     }
     52 }
     53 int qsum,qmx;
     54 void query(int u,int L,int R,int l,int r) {
     55     if(l<=L && R<=r)
     56         qsum+=T[u].sum , qmx=max(qmx,T[u].mx);
     57     else {
     58         int M=(L+R)>>1;
     59         if(l<=M) query(u<<1,L,M,l,r);
     60         if(M<r) query(u<<1|1,M+1,R,l,r);
     61     }
     62 }
     63 //树链剖分
     64 int query(int u,int v,int flag) {
     65     int sum=0,mx=-INF;
     66     while(top[u]!=top[v]) {
     67         if(dep[top[u]]<dep[top[v]]) swap(u,v);
     68         qsum=0 , qmx=-INF;
     69         query(1,1,z,w[top[u]],w[u]);
     70         sum+=qsum , mx=max(mx,qmx);
     71         u=fa[top[u]];
     72     }
     73     if(dep[u]>dep[v]) swap(u,v);
     74     qsum=0 , qmx=-INF;
     75     query(1,1,z,w[u],w[v]);
     76     sum+=qsum , mx=max(mx,qmx);
     77     return flag? sum:mx;
     78 }
     79 
     80 void read(int& x) {
     81     char c=getchar(); int f=1; x=0;
     82     while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
     83     while(isdigit(c)) x=x*10+c-'0',c=getchar();
     84     x*=f;
     85 }
     86 int main() {
     87     read(n);
     88     int u,v,x;
     89     FOR(i,1,n-1) {
     90         read(u),read(v);
     91         g[u].push_back(v);
     92         g[v].push_back(u);
     93     }
     94     dfs1(1),dfs2(1,1);
     95     FOR(i,1,n)
     96         read(x) , update(1,1,z,w[i],x);
     97     read(q);
     98     while(q--) {
     99         scanf("%s",s);
    100         read(u),read(v);
    101         if(s[0]=='C')  update(1,1,z,w[u],v);
    102         else
    103             if(s[1]=='M') printf("%d
    ",query(u,v,0));
    104             else printf("%d
    ",query(u,v,1));
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    在字符串中查找指定字符(15)
    说反话 (20)
    鼠标经过显示问题
    Java数据库连接池-proxool
    mysql中MAX()函数和count()函数的技巧使用
    Java中多线程问题
    eclipse开发文档模板
    方法调用中的别名问题
    php类的定义
    通知浏览器下载文件,而不是直接打开下载
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5186365.html
Copyright © 2020-2023  润新知