http://acm.hdu.edu.cn/showproblem.php?pid=3966
3 2 5 1 2 3 2 1 2 3 I 1 3 5 Q 2 D 1 2 2 Q 1 Q 3
7 4 8Hint1.The number of enemies may be negative. 2.Huge input, be careful.
/**
hdu3966  树链剖分(区间更新和单点求值)
题目大意:给定一棵树,对指定的连点之间的点的权进行更新,过程中询问指定点的当前值
解题思路:树链剖分,区间更新维护的题目
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=50005;
typedef long long LL;
int n,m,q,z;
LL a[maxn],sum[maxn*4],col[maxn*4];
int fa[maxn],Hash[maxn],dep[maxn],son[maxn],siz[maxn];
int num[maxn],top[maxn];
int head[maxn],ip;
void init()
{
    memset(head,-1,sizeof(head));
    memset(col,0,sizeof(col));
    memset(sum,0,sizeof(sum));
    ip=0;
}
struct note
{
    int v,next;
}edge[maxn*4];
void addedge(int u,int v)
{
    edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}
void dfs(int u,int pre)
{
    son[u]=0,siz[u]=1,dep[u]=dep[pre]+1,fa[u]=pre;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==pre)continue;
        dfs(v,u);
        if(siz[son[u]]<siz[v])
        {
            son[u]=v;
        }
        siz[u]+=siz[v];
    }
    ///printf("%d fa,dep,siz,son %d %d %d %d\n",u,fa[u],dep[u],siz[u],son[u]);
}
void set_que(int u,int tp)
{
    top[u]=tp,num[u]=++z,Hash[z]=u;
    if(son[u])
    {
        set_que(son[u],tp);
    }
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa[u]||v==son[u])continue;
        set_que(v,v);
    }
  ///  printf("%d top num %d %d\n",u,top[u],num[u]);
}
void push_up(int root)
{
    sum[root]=sum[root<<1]+sum[root<<1|1];
}
void build(int root,int l,int r)
{
    col[root]=0;
    if(l==r)
    {
        sum[root]=a[Hash[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    push_up(root);
}
void push_down(int root,int len)
{
    if(col[root])
    {
        col[root<<1]+=col[root];
        col[root<<1|1]+=col[root];
        sum[root<<1]+=col[root]*(len-(len>>1));
        sum[root<<1|1]+=col[root]*(len>>1);
        col[root]=0;
    }
}
void update(int root,int l,int r,int x,int y,int z)
{
    if(l>y||r<x)return;
    if(x<=l&&r<=y)
    {
        col[root]+=z;
        sum[root]+=(r-l+1)*z;
        return;
    }
    push_down(root,r-l+1);
    int mid=(l+r)>>1;
    update(root<<1,l,mid,x,y,z);
    update(root<<1|1,mid+1,r,x,y,z);
    push_up(root);
}
LL query(int root,int l,int r,int loc)
{
    if(l>loc||r<loc)return 0;
    if(l==r)
    {
        return sum[root];
    }
    push_down(root,r-l+1);
    int mid=(l+r)>>1;
    if(loc<=mid)
        return query(root<<1,l,mid,loc);
    else
        return query(root<<1|1,mid+1,r,loc);
}
int main()
{
   //freopen("data.txt","r",stdin);
    while(~scanf("%d%d%d",&n,&m,&q))
    {
        init();
        for(int i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
        }
        for(int i=0;i<m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        int root=(n+1)>>1;
        z=0,dep[0]=0,siz[0]=0;
        dfs(root,0);
        set_que(root,root);
        build(1,1,z);
        while(q--)
        {
            char s[20];
            int x,y,zz;
            scanf("%s",s);
            if(s[0]=='Q')
            {
                scanf("%d",&x);
                printf("%I64d\n",query(1,1,z,num[x]));
            }
            else
            {
                scanf("%d%d%d",&x,&y,&zz);
                if(s[0]=='D')zz=-zz;
                int f1=top[x],f2=top[y];
                while(f1!=f2)
                {
                    if(dep[f1]<dep[f2])
                    {
                        swap(f1,f2);
                        swap(x,y);
                    }
                    update(1,1,z,num[f1],num[x],zz);
                    x=fa[f1],f1=top[x];
                }
                if(dep[x]>dep[y])
                {
                    swap(x,y);
                }
                update(1,1,z,num[x],num[y],zz);
            }
        }
    }
    return 0;
}
原文:http://blog.csdn.net/lvshubao1314/article/details/46119007