树链剖分:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
包括点值,和段值的树链剖分
#pragma comment(linker, "/STACK:200000000")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
#include<vector>
using namespace std;
#define ll __int64
const ll N=100010;
ll vnode[N],vedge[N];
struct Edge
{
ll to,next;
}edge[N*2];
ll head[N],tot;
ll top[N];//top[v]表示v所在的重链的顶端节点
ll fa[N]; //父亲节点
ll deep[N];//深度
ll num[N];//num[v]表示以v为根的子树的节点数
ll p[N];//p[v]表示v与其父亲节点的连边在线段树中的位置
ll fp[N];//和p数组相反
ll son[N];//重儿子
ll pos;
int n;
void init()
{
tot=0;
memset(head,-1,(n+2)*sizeof(ll));
pos=1;
memset(son,-1,(n+2)*sizeof(ll));
}
void addedge(ll u,ll v)
{
edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++;
}
void dfs1(ll u,ll pre,ll d)//第一遍dfs求出fa,deep,num,son
{
deep[u]=d;
fa[u]=pre;
num[u]=1;
for(ll i=head[u];i!=-1;i=edge[i].next)
{
ll 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;
}
}
}
void getpos(ll u,ll sp)//第二遍dfs求出top和p
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1) return ;
getpos(son[u],sp);
for(ll i=head[u];i!=-1;i=edge[i].next)
{
ll v=edge[i].to;
if(v!=son[u] && v!=fa[u])
getpos(v,v);
}
}
ll e[100010][2];
void add1(ll u,ll v,ll val)//查询u->v边的最大值
{
ll f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
vnode[p[f1]]+=val;//p[f1],p[u]
vnode[p[u]+1]-=val;
u=fa[f1]; f1=top[u];
}
if(deep[u]>deep[v]) swap(u,v);//p[u],p[v]
vnode[p[u]]+=val;
vnode[p[v]+1]-=val;
}
void add2(ll u,ll v,ll val)//查询u->v边的最大值
{
ll f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
vedge[p[f1]]+=val;//p[f1],p[u];
vedge[p[u]+1]-=val;
u=fa[f1]; f1=top[u];
}
if(u==v) return ;
if(deep[u]>deep[v]) swap(u,v);//p[son[u]],p[v];
vedge[p[son[u]]]+=val;
vedge[p[v]+1]-=val;
}
ll read()
{
char c;
ll ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
return ret;
}
int main()
{
ll t;
scanf("%I64d",&t);
ll res=0;
while(t--)
{
res++;
ll m,i,j,k;
n=read();
m=read();
init();
int cnt=1;
for(i=1;i<n;i++)
{
scanf("%I64d%I64d",&e[i][0],&e[i][1]);
addedge(e[i][0],e[i][1]);
addedge(e[i][1],e[i][0]);
}
dfs1(1,0,0);
getpos(1,1);
char op[5];
memset(vnode,0,(n+2)*sizeof(ll));
memset(vedge,0,(n+2)*sizeof(ll));
while(m--)
{
ll a,b,c;
scanf("%s",op);
a=read();
b=read();
c=read();
if(op[3]=='1')
add1(a,b,c);
else
add2(a,b,c);
}
for(i=1;i<=n;i++)
{
vnode[i]+=vnode[i-1];
vedge[i]+=vedge[i-1];
}
printf("Case #%I64d:\n",res);
for(i=1;i<n;i++)
printf("%I64d ",vnode[p[i]]);
printf("%I64d\n",vnode[p[n]]);
for(i=1;i<n;i++)
{
if(deep[e[i][0]]>deep[e[i][1]])
swap(e[i][0],e[i][1]);
if(i!=n-1)
printf("%I64d ",vedge[p[e[i][1]]]);
else
printf("%I64d",vedge[p[e[i][1]]]);
}
printf("\n");
}
}