zoukankan      html  css  js  c++  java
  • HDU3966 Aragorn's Story 树链剖分

    题意:给你一棵树,每个节点有一个值,3种操作

    1)Q  u询问  某一个点的值。

    2)I  u v  w   把u,v之间(包括u,v)所有的点的值都加上 w 

    3) D u v w  把u,v之间(包括u,v)所有的点的值都减去 w 

    解题思路:树链剖分,树状数组记录改变值要比线段树快一点。

    解题代码:

      1 // File Name: 3966.2.cpp
      2 #pragma comment(linker, "/STACK:1024000000,1024000000")
      3 // Author: darkdream
      4 // Created Time: 2015年04月14日 星期二 11时01分25秒
      5 
      6 #include<vector>
      7 #include<list>
      8 #include<map>
      9 #include<set>
     10 #include<deque>
     11 #include<stack>
     12 #include<bitset>
     13 #include<algorithm>
     14 #include<functional>
     15 #include<numeric>
     16 #include<utility>
     17 #include<sstream>
     18 #include<iostream>
     19 #include<iomanip>
     20 #include<cstdio>
     21 #include<cmath>
     22 #include<cstdlib>
     23 #include<cstring>
     24 #include<ctime>
     25 #define LL long long
     26 #define maxn 50005
     27 using namespace std;
     28 int sz[maxn];
     29 int fa[maxn];
     30 int son[maxn];
     31 int top[maxn];
     32 int dep[maxn];
     33 int w[maxn];
     34 int totw;
     35 vector<int> mp[maxn];
     36 int tr[maxn];
     37 int val[maxn];
     38 int lowbit(int x)
     39 {
     40   return x & -x; 
     41 }
     42 int n; 
     43 void update(int x, int uv){
     44     //printf("%d %d
    ",x,uv);
     45     while(x <= n + 1){
     46         tr[x] += uv;
     47         x += lowbit(x);
     48     }
     49 }
     50 int getsum(int x){
     51     int sum = 0 ; 
     52     while(x >= 1)
     53     {
     54        sum += tr[x];
     55        x -= lowbit(x);
     56     }
     57     return sum ;
     58 }
     59 
     60 void dfs_1(int k,int la,int d){
     61     int num = mp[k].size();
     62     dep[k] = d; 
     63     fa[k] = la ; 
     64     sz[k] = 1; 
     65     son[k] = -1;
     66     for(int i = 0 ;i < num ;i ++){
     67         if(mp[k][i] != la){
     68             dfs_1(mp[k][i],k,d+1);
     69             sz[k] += sz[mp[k][i]];
     70             if(son[k] == -1 || sz[mp[k][i]] > sz[son[k]])
     71                 son[k] = mp[k][i];
     72         }
     73     }
     74 }
     75 void dfs_2(int k ,int sp)
     76 {
     77    top[k] = sp ; 
     78    if(son[k] != -1){
     79        w[k] = ++ totw ;
     80        dfs_2(son[k],sp);
     81    }else{ 
     82        w[k] = ++totw;
     83        return ;
     84    }
     85    int num = mp[k].size(); 
     86    for(int i = 0 ;i < num ;i ++){
     87         if(mp[k][i] != son[k] && mp[k][i] != fa[k]){
     88             dfs_2(mp[k][i],mp[k][i]);
     89         }
     90    }
     91 }
     92 void make(){
     93     totw = 0 ; 
     94     memset(tr,0,sizeof(tr));
     95     dfs_1(1,0,1);
     96     dfs_2(1,1);
     97 }
     98 void find(int u ,int v,  int uv){
     99     int f1 = top[u],f2= top[v];
    100     int tmp = 0 ; 
    101     while(f1 != f2){
    102         if(dep[f1] < dep[f2])
    103         {
    104             swap(u,v);
    105             swap(f1,f2);
    106         }
    107         update(w[f1],uv);
    108         update(w[u]+1,-uv);
    109         u = fa[f1];
    110         f1 = top[u];
    111     }
    112     if(dep[u] > dep[v]){    
    113         swap(u,v);
    114     }
    115     update(w[u],uv);
    116     update(w[v]+1,-uv);
    117 }//不停的更新u,v,一直到在同一条链上
    118 int main(){
    119     int m , q; 
    120     while(scanf("%d %d %d",&n,&m,&q) != EOF){
    121         for(int i = 1;i <= n;i ++)
    122             mp[i].clear();
    123         for(int i = 1;i <= n;i ++)
    124             scanf("%d",&val[i]);
    125         int u,v; 
    126         for(int i = 1;i < n;i ++){
    127             scanf("%d %d",&u,&v);
    128             mp[v].push_back(u);
    129             mp[u].push_back(v);
    130         }
    131         make();
    132         char op[10];
    133         while(q--)
    134         {
    135             scanf("%s",op);
    136             if(op[0] == 'Q'){
    137                 scanf("%d",&v);
    138                 printf("%d
    ",val[v] + getsum(w[v]));
    139                 continue;
    140             }
    141             int add; 
    142             scanf("%d %d %d",&u,&v,&add);
    143             if(op[0] == 'I')
    144                 find(u,v,add);
    145             else find(u,v,-add);
    146         }
    147     }
    148 return 0;
    149 }
    View Code
  • 相关阅读:
    Introduce myself
    二叉搜索树的后序遍历序列(剑指offer-23)
    从上到下打印二叉树(剑指offer-22)
    二叉树的深度(剑指offer-38)
    不用加减乘除做加法(剑指offer-48)
    栈的压入、弹出序列(剑指offer-21)
    Java容器
    包含min函数的栈(剑指offer-20)
    在Docker中创建Mongodb数据库
    词向量聚类实验
  • 原文地址:https://www.cnblogs.com/zyue/p/4425041.html
Copyright © 2011-2022 走看看