Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 700 Accepted Submission(s): 145
Problem Description
You 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.
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 ≤10 5),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, -10 5 ≤ k ≤ 10 5)
The first line of each case contains two integers N ,M (1 ≤ N, M ≤10 5),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, -10 5 ≤ k ≤ 10 5)
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.
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
题意:两种操作,将u和v路径之间点的权值+w,将u和v路径之间边的权值+w
思路:树链剖分裸题
这题就是类似于在一段区间上+一个数,可以用经典的方法,只需在区间头+w,在区间尾-w即可
先将树形转线性,然后对每条链进行上述操作就好了
对于边操作有一点要注意,因为每个点只与它父亲的边绑定,所以要更新u和v之间的边的时候,u和v的祖先f所绑定的边是不能更新的
因为那条边是不在u和v的路径上的
这题时间卡的紧,输入挂是必须的
#pragma comment(linker,"/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
using namespace std; typedef __int64 ll; const int MAXN = 100010; int head[MAXN]; int next[MAXN<<1]; int edge[MAXN<<1]; int esz; int deep[MAXN]; int son[MAXN]; int fa[MAXN]; int sz[MAXN]; int ord[MAXN]; int up[MAXN]; int ha[MAXN]; int bian[MAXN]; int id[MAXN<<1]; int dfs_clock; int n; ll ans1[MAXN]; ll ans2[MAXN]; ll ans3[MAXN]; ll ans4[MAXN]; inline int get(){ int ret=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)){ ret=ret*10+(int)(c-'0'); c=getchar(); } return ret; } void init() { memset(head,-1,sizeof(head)); memset(ans1,0,sizeof(ans1)); memset(ans2,0,sizeof(ans2)); esz=0;dfs_clock=0;deep[0]=0; } void add(int u,int v,int i) { edge[esz]=v; next[esz]=head[u]; id[esz]=i; head[u]=esz++; } void dfs(int u,int p) { fa[u]=p; deep[u]=deep[p]+1; sz[u]=1; son[u]=0; for(int i=head[u];i!=-1;i=next[i]){ int v=edge[i]; if(v==p)continue; dfs(v,u); bian[v]=id[i]; sz[u]+=sz[v]; if(!son[u] || sz[v] > sz[son[u]]){ son[u]=v; } } } void dfs1(int u,int p) { ord[u]=++dfs_clock; up[u]=p; ha[ord[u]]=u; if(!son[u])return; dfs1(son[u],p); for(int i=head[u];i!=-1;i=next[i]){ int v=edge[i]; if(v==fa[u] || v==son[u])continue; dfs1(v,v); } } void fx(int u,int v,int z) { int pu=up[u]; int pv=up[v]; while(pu != pv){ if(deep[pu]
deep[v])swap(u,v); ans1[ord[u]]+=z; ans1[ord[v]+1]-=z; } void fx2(int u,int v,int z) { int pu=up[u]; int pv=up[v]; while(pu != pv){ if(deep[pu]
deep[v])swap(u,v); ans2[ord[son[u]]]+=z; ans2[ord[v]+1]-=z; } int main() { int m; int t,tt=0; scanf("%d",&t); while(t--) { n=get();m=get(); init(); for(int i=1;i