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
思路:树链剖分。。常规做法要TLE、、、
这里先把链拆成线段,然后线扫描一遍、
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <cassert>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
work();
}
void scanf(int & x, char c = 0)
{
while((c = getchar()) < '0' || c > '9');
x = c - '0';
while((c = getchar()) >= '0' && c <= '9') x = x * 10 + (c - '0');
}
/*****************************************华丽分割线**********************************************/
#define maxn 200800
#define N 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int first[N],nxt[maxn],vv[maxn];
int fa[N],Pos[N],Size[N],Son[N],fPos[N];
int dep[N],Top[N];
char ope[10];
LL Ans1[N],Ans2[N];
int e,pos;
int firstadd[N],Nxt[10*maxn],Vv[10*maxn];
int firstadd2[N],Nxt2[10*maxn],Vv2[10*maxn];
int E,E2;
void scanf_f(int & a)
{
bool ok = 0;
a = 0;
char c;
while((c = getchar()) < '0' || c > '9')
{
if(c == '-') ok = 1;
}
a = c - '0';
while((c = getchar()) >= '0' && c <= '9')
a = a*10 + c - '0';
if(ok) a = -a;
}
void init(int n)
{
e = pos = E = E2 = 0;
memset(first,-1,sizeof(first));
memset(firstadd,-1,sizeof(firstadd));
memset(firstadd2,-1,sizeof(firstadd2));
memset(Son,-1,sizeof(Son));
}
void addedge(int u,int v)
{
vv[e] = v; nxt[e] = first[u]; first[u] = e++;
vv[e] = u; nxt[e] = first[v]; first[v] = e++;
}
void AddEdge(int u,int v)
{
Vv[E] = v; Nxt[E] = firstadd[u]; firstadd[u] = E++;
}
void AddEdge2(int u,int v)
{
Vv2[E2] = v; Nxt2[E2] = firstadd2[u]; firstadd2[u] = E2++;
}
void dfs(int u,int pre)
{
dep[u] = dep[pre] + 1;
Size[u] = 1;
for(int i = first[u];i != -1;i = nxt[i])
{
int v = vv[i];
if(v == pre) continue;
fa[v] = u;
dfs(v,u);
Size[u] += Size[v];
if(Son[u] == -1 || Size[v] > Size[Son[u]])
Son[u] = v;
}
}
void dfs2(int u,int t)
{
Pos[u] = ++pos;
fPos[pos] = u;
Top[u] = t;
if(Son[u] != -1)
dfs2(Son[u],t);
for(int i = first[u];i != -1;i = nxt[i])
{
int v = vv[i];
if(v != fa[u] && v != Son[u])
dfs2(v,v);
}
}
void gao(int u,int v,int add)
{
int f1 = Top[u],f2 = Top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(u,v);
swap(f1,f2);
}
AddEdge(Pos[f1],add);
AddEdge(Pos[u]+1,-add);
u = fa[f1]; f1 = Top[u];
}
if(dep[u] > dep[v]) swap(u,v);
AddEdge(Pos[u],add);
AddEdge(Pos[v]+1,-add);
}
void gao1(int u,int v,int add)
{
int f1 = Top[u],f2 = Top[v];
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(u,v);
swap(f1,f2);
}
if(f1 == u)
{
AddEdge2(Pos[f1],add);
AddEdge2(Pos[u]+1,-add);
}
else
{
AddEdge2(Pos[f1],add);
AddEdge2(Pos[u]+1,-add);
}
u = fa[f1]; f1 = Top[u];
}
if(dep[u] > dep[v]) swap(u,v);
AddEdge2(Pos[Son[u]],add);
AddEdge2(Pos[v]+1,-add);
}
struct Edge
{
int u,v;
}edge[N];
void work()
{
int t,cas = 0;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf_f(n);
scanf_f(m);
init(n);
for(int i = 1;i < n;i++)
{
int u,v;
scanf_f(u);
scanf_f(v);
addedge(u,v);
edge[i].u = u,edge[i].v = v;
}
dep[1] = 0;
dfs(1,1);
dfs2(1,1);
int u,v,k;
for(int i = 1;i <= m;i++)
{
scanf("%s",ope);
if(ope[3] == '1')
{
scanf_f(u);
scanf_f(v);
scanf_f(k);
gao(u,v,k);
}
else
{
scanf_f(u);
scanf_f(v);
scanf_f(k);
gao1(u,v,k);
}
}
printf("Case #%d:\n",++cas);
LL ans1 = 0,ans2 = 0;
for(int i = 1;i <= n;i++)
{
for(int j = firstadd[i];j != -1;j = Nxt[j])
ans1 += Vv[j];
for(int j = firstadd2[i];j != -1;j = Nxt2[j])
ans2 += Vv2[j];
Ans1[fPos[i]] = ans1;
Ans2[fPos[i]] = ans2;
}
for(int i = 1;i <= n;i++)
{
printf("%I64d",Ans1[i]);
if(i == n) puts("");
else printf(" ");
}
for(int i= 1;i < n;i++)
{
u = edge[i].u,v = edge[i].v;
if(dep[u] > dep[v]) swap(u,v);
printf("%I64d",Ans2[v]);
if(i != n-1)
printf(" ");
}
puts("");
}
}