树链剖分裸题。。。。
又要扩栈又要输入挂还卡格式。。。。真无语
Tree
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1538 Accepted Submission(s): 261
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
Source
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn=100100;
int nextInt()
{
char ch;
int ok=0,fu=0,ans=0;
while(ch=getchar())
{
if(ch=='-'||(ch>='0'&&ch<='9'))
{
ok=1;
if(ch=='-') fu=1;
else
{
ans=ans*10+(ch-'0');
}
}
else if(ok==1) break;
}
if(fu) ans=-ans;
return ans;
}
struct Edge
{
int to,next;
}edge[maxn*2];
int Adj[maxn],Size;
void add_edge(int u,int v)
{
edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++;
}
int fa[maxn],deep[maxn],num[maxn],son[maxn];
int top[maxn],p[maxn],rp[maxn],pos;
int tree[2][maxn],n,m;
inline int lowbit(int x)
{
return x&(-x);
}
void ADD(int id,int p,int v)
{
for(int i=p;i<=n;i+=lowbit(i))
tree[id][i]+=v;
}
int SUM(int id,int p)
{
int ret=0;
for(int i=p;i;i-=lowbit(i))
ret+=tree[id][i];
return ret;
}
void init()
{
memset(Adj,-1,sizeof(Adj));
memset(son,-1,sizeof(son));
memset(tree,0,sizeof(tree));
Size=0;pos=1;
}
void dfs1(int u,int pre,int d)
{
num[u]=1; fa[u]=pre; deep[u]=d;
for(int i=Adj[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre) continue;
dfs1(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[son[u]]<num[v])
{
son[u]=v;
}
}
}
void getP(int u,int tp)
{
top[u]=tp; p[u]=pos++; rp[p[u]]=u;
if(son[u]!=-1) getP(son[u],tp);
for(int i=Adj[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa[u]&&v!=son[u])
getP(v,v);
}
}
void Change(int u,int v,int k)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2); swap(u,v);
}
ADD(0,p[f1],k); ADD(0,p[u]+1,-k);
u=fa[f1]; f1=top[u];
}
if(deep[u]<deep[v]) swap(u,v);
ADD(0,p[v],k); ADD(0,p[u]+1,-k);
}
void Change2(int u,int v,int k)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2); swap(u,v);
}
ADD(1,p[f1]-1,k); ADD(1,p[u],-k);
u=fa[f1]; f1=top[u];
}
if(u==v) return ;
if(deep[u]<deep[v]) swap(u,v);
ADD(1,p[son[v]]-1,k);
ADD(1,p[u],-k);
}
int bian[maxn][2];
int main()
{
int T_T,cas=1;
scanf("%d",&T_T);
while(T_T--)
{
init();
scanf("%d%d",&n,&m);
for(int i=0;i<n-1;i++)
{
int a,b;
a=nextInt(); b=nextInt();
add_edge(a,b);
add_edge(b,a);
bian[i][0]=a;bian[i][1]=b;
}
dfs1(1,0,0);
getP(1,1);
for(int i=0;i<n-1;i++)
{
if(deep[bian[i][0]]<deep[bian[i][1]])
swap(bian[i][0],bian[i][1]);
}
while(m--)
{
char op[10];
int a,b,c;
scanf("%s",op);
a=nextInt(); b=nextInt(); c=nextInt();
if(op[3]=='1')
{
Change(a,b,c);
}
else if(op[3]=='2')
{
Change2(a,b,c);
}
}
printf("Case #%d:\n",cas++);
for(int i=1;i<=n;i++)
printf("%d%c",SUM(0,p[i]),(i==n)?'\n':' ');
for(int i=0;i<n-1;i++)
{
printf("%d%c",SUM(1,p[bian[i][0]]-1),(i==n-2)?'\n':' ');
}
if(n==1) putchar(10);
}
return 0;
}