HDU 5044 - Tree (树链剖分)
2014-09-28 09:18
477 查看
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 567 Accepted Submission(s): 121
Problem DescriptionYou are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N
There are N - 1 edges numbered from 1 to N - 1.
Each node has a value and each edge has a value. The initial value is 0.
There are two kind of operation as follows:
● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.
● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.
After finished M operation on the tree, please output the value of each node and edge.
Input
The first line of the input is T (1 ≤ T ≤ 20), which stands for the number of test cases you need to solve.
The first line of each case contains two integers N ,M (1 ≤ N, M ≤105),denoting the number of nodes and operations, respectively.
The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.
For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -105 ≤ k ≤ 105)
Output
For each test case, print a line “Case #t:”(without quotes, t means the index of the test case) at the beginning.
The second line contains N integer which means the value of each node.
The third line contains N - 1 integer which means the value of each edge according to the input order.
Sample Input
2 4 2 1 2 2 3 2 4 ADD1 1 4 1 ADD2 3 4 2 4 2 1 2 2 3 1 4 ADD1 1 4 5 ADD2 3 2 4
Sample Output
Case #1: 1 1 0 1 0 2 2 Case #2: 5 0 0 5 0 4 0
Source
2014 ACM/ICPC Asia Regional Shanghai Online
Recommend
hujie | We have carefully selected several similar problems for you: 5053 5052 5051 5050 5049
Statistic | Submit | Discuss | Note
题意:
一棵树,初始点权和边权都为0。
两种操作
add1 u v d : u -> v之间的所有点权值+d
add2 u v d : u -> v之间的所有边权值+d
树链剖分入门模板题
比赛的时候才学的竟然很顺利的A了
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <string> #include <map> #include <cmath> #include <queue> #include <set> using namespace std; #define WIN #ifdef WIN typedef __int64 LL; #define iform "%I64d" #define oform "%I64d\n" #define oform1 "%I64d" #else typedef long long LL; #define iform "%lld" #define oform "%lld\n" #define oform1 "%lld" #endif #define S64I(a) scanf(iform, &(a)) #define P64I(a) printf(oform, (a)) #define P64I1(a) printf(oform1, (a)) #define REP(i, n) for(int (i)=0; (i)<n; (i)++) #define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++) #define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++) const int INF = 0x3f3f3f3f; const double eps = 1e-9; const double PI = (4.0*atan(1.0)); using namespace std; const int maxn = 100000 + 20; const int maxo = maxn * 4; struct Edge { int to,next; } edge[maxn*2]; int head[maxn], tot; int top[maxn]; // top[v]表示v所在的重链的顶端节点 int fa[maxn]; // 父亲节点 int deep[maxn]; // 深度 int num[maxn]; // num[v]表示以v为根的子树的节点数 int p[maxn]; // p[v]表示v与其父亲节点的连边在线段树中的位置 int fp[maxn]; // 和p数组相反 int son[maxn]; // 重儿子 int pos; // 对应区间计数器 void init() { tot = 0; memset(head, -1, sizeof(head)); pos = 1; memset(son, -1, sizeof(son)); } void addedge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } // 第一遍dfs求出fa, deep, num, son // u当前节点, pre为父节点, d为深度 void dfs1(int u, int pre, int d) { deep[u] = d; fa[u] = pre; num[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != pre) { dfs1(v, u, d+1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } } // 第二遍dfs求出top和p // sp为当前点所在重链的顶节点 void dfs2(int u, int sp) { top[u] = sp; p[u] = pos++; fp[p[u]] = u; if(son[u] == -1) return; dfs2(son[u], sp); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u]) dfs2(v, v); } } // 区间+d,最后求每个点的值 // 离线标记法 LL Seg[maxn][2]; void SegAdd(int L, int R, LL v, int d) { Seg[L][d] += v; Seg[R+1][d] -= v; } void GetSeg(int L, int R, int d) { LL cur = Seg[L][d]; for(int i=L+1; i<=R; i++) { LL t = Seg[i][d]; Seg[i][d] += cur; cur += t; } } // u <-> v 的所有点权值+d void add1(int u, int v, int d) { int qd = 0, qv = d; int ql, qr; while(top[u] != top[v]) { if(deep[top[u]] < deep[top[v]]) swap(u, v); // 对应区间是p[top[u]] -> p[u]; ql = p[top[u]], qr = p[u]; SegAdd(ql, qr, qv, qd); u = fa[top[u]]; } if(deep[u] > deep[v]) swap(u, v); ql = p[u], qr = p[v]; SegAdd(ql, qr, qv, qd); } // u <-> v 的所有边权值+d void add2(int u, int v, int d) { int f1 = top[u], f2 = top[v]; int qd = 1, qv = d; int ql, qr; while(top[u] != top[v]) { if(deep[top[u]] < deep[top[v]]) swap(u, v); // 对应区间是p[top[u]] -> p[u]; ql = p[top[u]], qr = p[u]; SegAdd(ql, qr, qv, qd); u = fa[top[u]]; } if(u == v) return ; if(deep[u] > deep[v]) swap(u,v); // 注意区间是p[son[u]] -> p[v] ql = p[son[u]], qr = p[v]; SegAdd(ql, qr, qv, qd); } int eu[maxn], ev[maxn]; char str[10]; int main() { int T; scanf("%d", &T); for(int kase=1; kase<=T; kase++) { int n, m; init(); printf("Case #%d:\n", kase); scanf("%d%d", &n, &m); for(int i=0; i<n-1; i++) { scanf("%d%d", &eu[i], &ev[i]); addedge(eu[i], ev[i]); addedge(ev[i], eu[i]); } dfs1(1, 1, 1); dfs2(1, 1); memset(Seg, 0, sizeof(Seg)); for(int i=0; i<m; i++) { int u, v, d; scanf("%s%d%d%d", str, &u, &v, &d); if(str[3] == '1') { add1(u, v, d); } else { add2(u, v, d); } } GetSeg(1, pos-1, 0); GetSeg(1, pos-1, 1); for(int i=1; i<=n; i++) { LL ans = Seg[p[i]][0]; if(i > 1) putchar(' '); P64I1(ans); } putchar('\n'); for(int i=0; i<n-1; i++) { int u = eu[i], v = ev[i]; if(deep[u] < deep[v]) swap(u, v); LL ans = Seg[p[u]][1]; if(i) putchar(' '); P64I1(ans); } putchar('\n'); } return 0; }
相关文章推荐
- hdu_5044_Tree(树链剖分)
- HDU 5044 Tree (树链剖分+数组lazy-tag)
- HDU-5044 Tree 树链剖分
- HDU 5044 Tree(树链剖分)
- hdu 5044 Tree(树链剖分)
- HDU 5044 Tree (树链剖分)
- hdu 5044 Tree 树链剖分
- 【HDU】5044 Tree 树链剖分
- HDU 5044 Tree --树链剖分
- HDU 5044-tree-树链剖分+树状数组
- HDU 5044 Tree 树链剖分
- HDU 5044 Tree 树链剖分
- HDU 5044 - Tree (树链剖分)
- HDU 5044 Tree 树链剖分+区间标记
- hdu_5044_Tree(树链剖分)
- HDU 5044 Tree --树链剖分
- HDU 5044 Tree (树链剖分+区间更新)
- HDU 5044 Tree(树链剖分)
- HDU 5044 Tree 树链剖分
- HDU 5044 Tree 树链剖分