Hdu--5044(树链剖分,处理点、边)

2014-10-08 21:43:43

思路:这题写了好久,一开始直接树链剖分,果断TLE。后来发现可以把加法树也转化为线性结构(核心思想),当然用树状数组也可以。

  关于处理边的方法:把边的编号对应到它的较深点,形象的理解为边下沉一级。所以处理边时,在遍历树链时要格外注意。

  1 /*************************************************************************
  2     > File Name: 5044.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Mon 06 Oct 2014 10:13:01 PM CST
  6 ************************************************************************/
  7 
  8 #pragma comment(linker,"/STACK:1024000000,1024000000")
  9 #include <cstdio>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <cmath>
 13 #include <vector>
 14 #include <map>
 15 #include <set>
 16 #include <queue>
 17 #include <iostream>
 18 #include <algorithm>
 19 using namespace std;
 20 #define lp (p << 1)
 21 #define rp (p << 1|1)
 22 #define getmid(l,r) (l + (r - l) / 2)
 23 #define MP(a,b) make_pair(a,b)
 24 typedef long long ll;
 25 const int INF = 1 << 30;
 26 const int maxn = 100010;
 27 
 28 int T,N,M;
 29 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt;
 30 int id[maxn << 1],aid[maxn];
 31 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn];
 32 int w[maxn],aw[maxn],tsz;
 33 ll it1[maxn],it2[maxn],val1[maxn],val2[maxn];
 34 
 35 void Init(){
 36     memset(it1,0,sizeof(it1));
 37     memset(it2,0,sizeof(it2));
 38     memset(first,-1,sizeof(first));
 39     memset(val1,0,sizeof(val1));
 40     memset(val2,0,sizeof(val2));
 41     ecnt = 0;
 42     tsz = 0;
 43 }
 44 
 45 inline int Read(){
 46     int x = 0,f = 1;char ch = getchar();
 47     while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}
 48     while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
 49     return x * f;
 50  }
 51 
 52 void Add_edge(int u,int v,int i){
 53     next[++ecnt] = first[u];
 54     ver[ecnt] = v;
 55     id[ecnt] = i;
 56     first[u] = ecnt;
 57     next[++ecnt] = first[v];
 58     ver[ecnt] = u;
 59     id[ecnt] = i;
 60     first[v] = ecnt;
 61 }
 62 
 63 void Dfs(int p,int pre,int d){
 64     sz[p] = 1;
 65     dep[p] = d;
 66     son[p] = -1;
 67     fa[p] = pre;
 68     int v,tmp = 0;
 69     for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){
 70         aid[v] = id[i];
 71         Dfs(v,p,d + 1);
 72         if(sz[v] > tmp){
 73             tmp = sz[v];
 74             son[p] = v;
 75         }
 76         sz[p] += sz[v];
 77     }
 78 }
 79 
 80 void Dfs_pos(int p,int tp){
 81     w[p] = ++tsz;
 82     aw[tsz] = p;
 83     top[p] = tp;
 84     if(son[p] != -1) Dfs_pos(son[p],tp);
 85     for(int i = first[p]; i != -1; i = next[i]){
 86         int v = ver[i];
 87         if(v != son[p] && v != fa[p])
 88             Dfs_pos(v,v);
 89     }
 90 }
 91 
 92 void Update1(int a,int b,int c){
 93     int f1 = top[a],f2 = top[b];
 94     while(f1 != f2){
 95         if(dep[f1] > dep[f2]){
 96             swap(a,b);
 97             swap(f1,f2);
 98         }
 99         it1[w[f2]] += c;
100         it1[w[b] + 1] -= c;
101         b = fa[f2];
102         f2 = top[b];
103     }
104     if(dep[a] > dep[b]) swap(a,b);
105     it1[w[a]] += c;
106     it1[w[b] + 1] -= c;
107 }
108 
109 void Update2(int a,int b,int c){
110     int f1 = top[a],f2 = top[b];
111     while(f1 != f2){
112         if(dep[f1] > dep[f2]){
113             swap(a,b);
114             swap(f1,f2);
115         }
116         it2[w[f2]] += c;
117         it2[w[b] + 1] -= c;
118         b = fa[f2];
119         f2 = top[b];
120     }
121     if(dep[a] > dep[b]) swap(a,b);
122     it2[w[son[a]]] += c;
123     it2[w[b] + 1] -= c;
124 }
125 
126 int main(){
127     char s[10];
128     int a,b,c;
129     T = Read();
130     for(int Case = 1; Case <= T; ++Case){
131         Init();
132         N = Read();
133         M = Read();
134         for(int i = 1; i < N; ++i){
135             a = Read(),b = Read();
136             Add_edge(a,b,i);
137         }
138         Dfs(1,0,0);
139         Dfs_pos(1,1);
140         while(M--){
141             scanf("%s",s);
142             a = Read(),b = Read(),c = Read();
143             if(s[3] == '1'){
144                 Update1(a,b,c);
145             }
146             else{
147                 Update2(a,b,c);
148             }
149         }
150         printf("Case #%d:\n",Case);
151         it1[0] = it2[1] = 0;
152         for(int i = 1; i <= N; ++i){
153             it1[i] += it1[i - 1];
154             val1[aw[i]] = it1[i];
155         }
156         for(int i = 2; i <= N; ++i){
157             it2[i] += it2[i - 1];
158             val2[aid[aw[i]]] = it2[i];
159         }
160         for(int i = 1; i <= N; ++i){
161             if(i != 1) printf(" ");
162             printf("%I64d",val1[i]);
163         }
164         puts("");
165         if(N > 1){
166             for(int i = 1; i < N; ++i){
167                 if(i != 1) printf(" ");
168                 printf("%I64d",val2[i]);
169             }
170         }
171         puts("");
172     }
173     return 0;
174 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4012123.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值