hdu 3966 Aragorn's Story 树链剖分

本文详细介绍了如何使用树链剖分算法解决HDU 3966题目,包括算法分析、代码实现以及解决过程中需要注意的细节。通过手动扩栈来避免栈溢出的问题,确保了程序的稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: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\n",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 }

 

 

转载于:https://www.cnblogs.com/huangxf/p/4342486.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值