Hdu--5029(树链剖分,思维深化,巧建线段树)

2014-10-10 22:37:06

思路:这题给树链剖分学习的第一个阶段画上了一个句号,一开始看的时候线段树乱搞都没搞出来 orz。后来看了结题报告发现自己 too young。

  首先把点构成的树剖分是没有悬念的,接下来如果直接用线段树搞的话,节点维护什么呢?每种颜色及其次数吗?显然不行。转换下思路,这题其实和上海网赛的那题有点像,只不过这题少了边处理,只有点处理。由于算法可以离线,更新次数多,但查询只有一次(即:最后把所有点的信息输出),所以可以把更新操作(树上路径更新)用树剖转化为线性结构上的更新操作!这个转化其实就是树链剖分算法思想的最好体现。所以对每个更新如:[a,b],c ,用两个标记记录 f[a] += c , f[b + 1] -= c,因为要记录所有 c ,所以 f[]可以是向量数组,f[a].push_back(c) , f[b + 1].push_back(-c),最后扫一遍点就出来了。

  1 /*************************************************************************
  2     > File Name: 5029.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Fri 10 Oct 2014 08:34:44 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <queue>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 #define lp (p << 1)
 20 #define rp (p << 1|1)
 21 #define getmid(l,r) (l + (r - l) / 2)
 22 #define MP(a,b) make_pair(a,b)
 23 typedef long long ll;
 24 const int INF = 1 << 30;
 25 const int maxn = 100010;
 26 
 27 inline int Read(){
 28     int x = 0;
 29     char c = getchar();
 30     while(c < '0' || c > '9') c = getchar();
 31     while(c >= '0' && c <= '9'){ x = x * 10 + c - '0'; c = getchar();}
 32     return x;
 33 }
 34 
 35 int n,m;
 36 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt;
 37 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn],w[maxn],aw[maxn],tsz;
 38 int tmax[maxn << 2],col[maxn << 2],ans[maxn];
 39 vector<int> f[maxn];
 40 
 41 void Init(){
 42     for(int i = 1; i <= n; ++i) f[i].clear();
 43     memset(col,0,sizeof(col));
 44     memset(tmax,0,sizeof(tmax));
 45     memset(first,-1,sizeof(first));
 46     ecnt = tsz = 0;
 47 }
 48 
 49 void Add_edge(int u,int v){
 50     next[++ecnt] = first[u];
 51     ver[ecnt] = v;
 52     first[u] = ecnt;
 53 }
 54 
 55 void Dfs(int p,int pre,int d){
 56     sz[p] = 1;
 57     son[p] = -1;
 58     fa[p] = pre;
 59     dep[p] = d;
 60     int v,tmp = 0;
 61     for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){
 62         Dfs(v,p,d + 1);
 63         if(sz[v] > tmp){
 64             tmp = sz[v];
 65             son[p] = v;
 66         }
 67         sz[p] += sz[v];
 68     }
 69 }
 70 
 71 void Dfs_pos(int p,int tp){
 72     w[p] = ++tsz;
 73     aw[tsz] = p;
 74     top[p] = tp;
 75     if(son[p] != -1) Dfs_pos(son[p],tp);
 76     for(int i = first[p]; i != -1; i = next[i]){
 77         int v = ver[i];
 78         if(v != son[p] && v != fa[p])
 79             Dfs_pos(v,v);
 80     }
 81 }
 82 
 83 void Change(int a,int b,int c){
 84     int f1 = top[a],f2 = top[b];
 85     while(f1 != f2){
 86         if(dep[f1] > dep[f2]){
 87             swap(a,b);
 88             swap(f1,f2);
 89         }
 90         f[w[f2]].push_back(c);
 91         f[w[b] + 1].push_back(-c);
 92         b = fa[f2];
 93         f2 = top[b];
 94     }
 95     if(dep[a] > dep[b]) swap(a,b);
 96     f[w[a]].push_back(c);
 97     f[w[b] + 1].push_back(-c);
 98 }
 99 
100 void Update_tree(int a,int c,int p,int l,int r){
101     if(l == r){
102         tmax[p] += c;
103         if(tmax[p] > 0) col[p] = l;
104         else col[p] = 0;
105         return;
106     }
107     int mid = getmid(l,r);
108     if(a <= mid) Update_tree(a,c,lp,l,mid);
109     else Update_tree(a,c,rp,mid + 1,r);
110     if(tmax[lp] >= tmax[rp]){
111         tmax[p] = tmax[lp];
112         col[p] = col[lp];
113     }
114     else{
115         tmax[p] = tmax[rp];
116         col[p] = col[rp];
117     }
118 }
119 
120 int main(){
121     int a,b,c;
122     while(1){
123         n = Read(),m = Read();
124         if(!n && !m) break;
125         Init();
126         for(int i = 1; i < n; ++i){
127             a = Read(),b = Read();
128             Add_edge(a,b);
129             Add_edge(b,a);
130         }
131         Dfs(1,0,0);
132         Dfs_pos(1,1);
133         for(int i = 1; i <= m; ++i){
134             a = Read();
135             b = Read();
136             c = Read();
137             Change(a,b,c);
138         }
139         for(int i = 1; i <= n; ++i){
140             for(unsigned int j = 0; j < f[i].size(); ++j)
141                 Update_tree(abs(f[i][j]),f[i][j] > 0 ? 1 : -1,1,1,maxn);
142             ans[aw[i]] = col[1];
143         }
144         for(int i = 1; i <= n; ++i)
145             printf("%d\n",ans[i]);
146     }
147     return 0;
148 }

 

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值