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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966

    Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, the enemy has N camps out of his kingdom and M edges connect them. It is guaranteed that for any two camps, there is one and only one path connect them. At first Aragorn know the number of enemies in every camp. But the enemy is cunning , they will increase or decrease the number of soldiers in camps. Every time the enemy change the number of soldiers, they will set two camps C1 and C2. Then, for C1, C2 and all camps on the path from C1 to C2, they will increase or decrease K soldiers to these camps. Now Aragorn wants to know the number of soldiers in some particular camps real-time. 
     
    题意描述:给定一棵树和节点上的值,然后执行下面操作:
    I u,v,value:把u和v路径上的节点的值都加上value;
    D u,v,value:把u和v路径上的节点的值都减去value;
    Q u:询问节点u上的值。
     
    算法分析:最近学习树链剖分,就把这道题作为入门题练习。这里有树链剖分的基础
    这道题很容易爆栈,所以得手动扩栈。
      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<algorithm>
      8 #include<queue>
      9 #include<vector>
     10 #define inf 0x7fffffff
     11 #define lson l,m,rt<<1
     12 #define rson m+1,r,rt<<1|1
     13 using namespace std;
     14 typedef long long LL;
     15 const int maxn=50000+10;
     16 
     17 int n,m,q;
     18 int siz[maxn],son[maxn],val[maxn],dep[maxn];
     19 int tid[maxn],tid2[maxn],tot;
     20 int fa[maxn],top[maxn];
     21 vector<int> G[maxn];
     22 
     23 void dfs1(int u,int father,int d)
     24 {
     25     dep[u]=d;
     26     fa[u]=father;
     27     siz[u]=1;
     28     for (int i=0 ;i<G[u].size() ;i++)
     29     {
     30         int v=G[u][i];
     31         if(v!=father)
     32         {
     33             dfs1(v,u,d+1);
     34             siz[u]+=siz[v];
     35             if(son[u]==-1||siz[v]>siz[son[u]])
     36                 son[u]=v;
     37         }
     38     }
     39 }
     40 
     41 void dfs2(int u,int tp)
     42 {
     43     top[u]=tp;
     44     tid[u]= ++tot;
     45     tid2[tid[u]]=u;
     46     if (son[u]==-1) return;
     47     dfs2(son[u],tp);
     48     for (int i=0 ;i<G[u].size() ;i++)
     49     {
     50         int v=G[u][i];
     51         if(v!=son[u]&&v!=fa[u])
     52             dfs2(v,v);
     53     }
     54 }
     55 
     56 int sum[maxn<<2],col[maxn<<2];
     57 void PushUP(int rt)
     58 {
     59     sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
     60 }
     61 
     62 void PushDown(int rt,int len)
     63 {
     64     if (col[rt]!=0)
     65     {
     66         col[rt<<1] += col[rt];
     67         col[rt<<1|1] += col[rt];
     68         sum[rt<<1] += (len-(len>>1))*col[rt];
     69         sum[rt<<1|1] += (len>>1)*col[rt];
     70         col[rt]=0;
     71     }
     72 }
     73 
     74 void build(int l,int r,int rt)
     75 {
     76     col[rt]=0;
     77     if (l==r)
     78     {
     79         sum[rt]=val[tid2[l] ];
     80         return ;
     81     }
     82     int mid=(l+r)>>1;
     83     build(l,mid,rt<<1);
     84     build(mid+1,r,rt<<1|1);
     85     PushUP(rt);
     86 }
     87 
     88 void update(int L,int R,int value,int l,int r,int rt)
     89 {
     90     if (L<=l && r<=R)
     91     {
     92         sum[rt] += (r-l+1)*value;
     93         col[rt] += value;
     94         return ;
     95     }
     96     PushDown(rt,(r-l+1));
     97     int mid=(l+r)>>1;
     98     if (L<=mid) update(L,R,value,l,mid,rt<<1);
     99     if (R>mid) update(L,R,value,mid+1,r,rt<<1|1);
    100     PushUP(rt);
    101 }
    102 
    103 int query(int l,int r,int rt,int u)
    104 {
    105     if (l==r) return sum[rt];
    106     PushDown(rt,r-l+1);
    107     int mid=(l+r)>>1;
    108     int ans;
    109     if (u<=mid) ans=query(l,mid,rt<<1,u);
    110     else ans=query(mid+1,r,rt<<1|1,u);
    111     PushUP(rt);
    112     return ans;
    113 }
    114 
    115 void solve(int u,int v,int value)
    116 {
    117     int f1=top[u],f2=top[v];
    118     while (f1 != f2)
    119     {
    120         if (dep[f1]<dep[f2]) {swap(f1,f2);swap(u,v); }
    121         update(tid[f1],tid[u],value,1,n,1);
    122         u=fa[f1] ;f1=top[u] ;
    123     }
    124     if (dep[u]<dep[v]) swap(u,v);
    125     update(tid[v],tid[u],value,1,n,1);
    126 }
    127 
    128 int main()
    129 {
    130     while (scanf("%d%d%d",&n,&m,&q)!=EOF)
    131     {
    132         memset(sum,0,sizeof(sum));
    133         memset(col,0,sizeof(col));
    134         memset(son,-1,sizeof(son));
    135         tot=0;
    136         for (int i=1 ;i<=n ;i++) scanf("%d",&val[i]);
    137         int u,v,value;
    138         char str[3];
    139         for (int i=1 ;i<=n ;i++) G[i].clear();
    140         for (int i=1 ;i<=m ;i++)
    141         {
    142             scanf("%d%d",&u,&v);
    143             G[u].push_back(v);
    144             G[v].push_back(u);
    145         }
    146         dfs1(1,0,0);
    147         dfs2(1,1);
    148         build(1,n,1);
    149         while (q--)
    150         {
    151             scanf("%s",str);
    152             if (str[0]=='Q')
    153             {
    154                 scanf("%d",&u);
    155                 printf("%d
    ",query(1,n,1,tid[u]));
    156             }
    157             else
    158             {
    159                 scanf("%d%d%d",&u,&v,&value);
    160                 if (str[0]=='D') value=-value;
    161                 solve(u,v,value);
    162             }
    163         }
    164     }
    165     return 0;
    166 }
     
  • 相关阅读:
    ubuntu下内核源码树的建立
    删除ubuntu旧版本内核
    设置ubuntu12.04桌面版开机进入命令行模式
    MFC学习笔记(一)向模态对话框传递数据
    redis 映射数据结构粗略
    redis入门
    mybatis总结
    mybatis--mapper配置总结
    mybatis-初步使用
    maven-plugins说明
  • 原文地址:https://www.cnblogs.com/huangxf/p/4342486.html
Copyright © 2011-2022 走看看