首页 > 代码库 > HDU5044---Tree 树链剖分

HDU5044---Tree 树链剖分

大致题意:add1 u v   u到v路径上所有点的权值加上k,add2  u 到v路径上所有边的权值加上k

最后输出所有点的权值,边的权值。。树链剖分预处理然后来个线性O(n)的操作。刚开始用线段树tle了.

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")  2 #include <cstdio>  3 #include <cstdlib>  4 #include <cstring>  5 #include <iostream>  6 #include <algorithm>  7 using namespace std;  8 typedef unsigned long long ull;  9 typedef long long ll; 10 const int inf = 0x3f3f3f3f; 11 const int maxn = 1e5+10; 12 struct 13 { 14     int  to,next; 15 } e[maxn<<1]; 16 int head[maxn],edge; 17 void add(int x,int y) 18 { 19     e[edge].to = y; 20     e[edge].next = head[x]; 21     head[x] = edge++; 22 } 23  24 int son[maxn],fa[maxn],siz[maxn],dep[maxn]; 25 void dfs1(int root) 26 { 27     siz[root] = 1; 28     son[root] = 0; 29     for (int i = head[root]; i > 0; i = e[i].next) 30     { 31         if (fa[root] != e[i].to) 32         { 33             dep[e[i].to] = dep[root] + 1; 34             fa[e[i].to] = root; 35             dfs1(e[i].to); 36             if (siz[son[root]] < siz[e[i].to]) 37                 son[root] = e[i].to; 38             siz[root] += siz[e[i].to]; 39         } 40     } 41 } 42 int top[maxn],pos[maxn],fp[maxn],tot; 43 void dfs2(int root,int f) 44 { 45     top[root] = f; 46     pos[root] = tot++; 47     fp[pos[root]] = root; 48     if (son[root]>0) 49         dfs2(son[root],top[root]); 50     for (int i = head[root]; i > 0; i = e[i].next) 51         if (fa[root] != e[i].to && e[i].to != son[root]) 52             dfs2(e[i].to,e[i].to); 53 } 54 ll addv[3][maxn<<2]; 55 int k; 56 void pre_update(int ua,int ub,int cho) 57 { 58     int f1 = top[ua]; 59     int f2 = top[ub]; 60     while (f1 != f2) 61     { 62         if (dep[f1] < dep[f2]) 63             swap(f1,f2),swap(ua,ub); 64         addv[cho][pos[f1]] += k; 65         addv[cho][pos[ua]+1] -= k; 66         ua = fa[f1]; 67         f1 = top[ua]; 68     } 69     if (dep[ua] > dep[ub]) 70         swap(ua,ub); 71     if (cho == 1) 72         addv[cho][pos[ua]] += k,addv[cho][pos[ub]+1] -= k; 73     if (cho == 2) 74         addv[cho][pos[son[ua]]] += k,addv[cho][pos[ub]+1] -= k; 75 } 76 int n,m,d[maxn][2],link[maxn]; 77 void init() 78 { 79     scanf ("%d%d",&n,&m); 80     int root = 1; 81     dep[root] = fa[root] = 0; 82     edge = tot = 1; 83     memset(head,0,sizeof(head)); 84     memset(siz,0,sizeof(siz)); 85     memset(addv,0,sizeof(addv)); 86     for (int i = 1; i < n; i++) 87     { 88         int u,v; 89         scanf ("%d%d",&u,&v); 90         d[i][0] = u; 91         d[i][1] = v; 92         add(u,v),add(v,u); 93     } 94     dfs1(root); 95     dfs2(root,root); 96     for (int i = 1; i < n; i++) 97     { 98         if (dep[d[i][0]] < dep[d[i][1]]) 99             swap(d[i][0],d[i][1]);100         link[d[i][0]] = i;101     }102 }103 ll ans1[maxn],ans2[maxn];104 int main(void)105 {106     //freopen("in.txt","r",stdin);107     int t;108     int cas = 1;109     scanf ("%d",&t);110     while (t--)111     {112         init();113         for (int i = 0; i < m; i++)114         {115             char op[10];116             int u,v;117             scanf ("%s%d%d%d",op,&u,&v,&k);118             pre_update(u,v,op[3]-0);119         }120         for (int i = 1; i <= n; i++)121         {122             addv[1][i] += addv[1][i-1];123             addv[2][i] += addv[2][i-1];124             ans1[fp[i]] = addv[1][i];125             ans2[link[fp[i]]] = addv[2][i];126         }127         printf("Case #%d:\n",cas++);128         printf("%I64d",ans1[1]);129         for (int i = 2; i <= n; i++)130         {131             printf(" %I64d",ans1[i]);132         }133         printf("\n");134         if (n>1)135             printf("%I64d",ans2[1]);136         for (int i = 2; i < n; i++)137         {138             printf(" %I64d",ans2[i]);139         }140         printf("\n");141     }142     return 0;143 }
View Code

 

HDU5044---Tree 树链剖分