hdu 3966 树链剖分

思路:树链剖分入门题,我这门入得好苦啊,程序很快写出来了,可是在LCA过程中把update函数里的左右边界位置写反了,一直RE到死。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pb push_back
#define mp make_pair
#define Maxn 50010
#define Maxm 200010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 100000
#define lowbit(x) (x&(-x))
#define clr(x,y) memset(x,y,sizeof(x))
#define Mod 1000000007
using namespace std;
int head[Maxn],vi[Maxn],dep[Maxn],w[Maxn],top[Maxn],son[Maxn],sz[Maxn],fa[Maxn],e,id;
int num[Maxn];
struct Edge{
    int u,v,next;
}edge[Maxn*3];
struct Tree{
    int l,r,c;
    int mid(){
        return (l+r)>>1;
    }
}tree[Maxn*3];
void init()
{
    clr(head,-1);clr(vi,0);
    e=0;id=0;
}
void add(int u,int v)
{
    edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
}
void BuildTree(int l,int r,int po)
{
    tree[po].l=l,tree[po].r=r,tree[po].c=0;
    if(l==r)
        return ;
    int mid=tree[po].mid();
    BuildTree(l,mid,lson(po));
    BuildTree(mid+1,r,rson(po));
}
void down(int po)
{
    tree[lson(po)].c+=tree[po].c;
    tree[rson(po)].c+=tree[po].c;
    tree[po].c=0;
}
void update(int l,int r,int c,int po)
{
    if(l<=tree[po].l&&tree[po].r<=r){
        tree[po].c+=c;
        return ;
    }
    down(po);
    int mid=tree[po].mid();
    if(r<=mid)
        update(l,r,c,lson(po));
    else if(l>=mid+1)
        update(l,r,c,rson(po));
    else {
        update(l,mid,c,lson(po));
        update(mid+1,r,c,rson(po));
    }
}
int getans(int i,int po)
{
    if(tree[po].l==tree[po].r){
        return tree[po].c;
    }
    down(po);
    int mid=tree[po].mid();
    if(i<=mid)
        return getans(i,lson(po));
    else
        return getans(i,rson(po));
}
void dfs(int u)
{
    vi[u]=1;
    int i,v;
    son[u]=0,sz[u]=1;
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(vi[v]) continue;
        dep[v]=dep[u]+1;
        fa[v]=u;
        dfs(v);
        if(sz[v]>sz[son[u]])son[u]=v;
        sz[u]+=sz[v];
    }
}
void build(int u,int ti)
{
    int i,v;
    w[u]=++id;top[u]=ti;vi[u]=1;
    if(son[u]) build(son[u],ti);
    for(i=head[u];i!=-1;i=edge[i].next){
        v=edge[i].v;
        if(vi[v]||v==son[u]) continue;
        build(v,v);
    }
}
void calc(int u,int v,int c)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2){
        if(dep[f1]<dep[f2]){
            swap(f1,f2),swap(u,v);
        }
        update(w[f1],w[u],c,1);
        u=fa[f1];f1=top[u];
    }
    if(dep[u]>dep[v])
        swap(u,v);
    update(w[u],w[v],c,1);
    return ;
}
int main()
{
    int n,m,p,i,j,u,v,val;
    char str[10];
    while(scanf("%d%d%d",&n,&m,&p)!=EOF){
        init();
        for(i=1;i<=n;i++)
            scanf("%d",num+i);
        for(i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1);
        clr(vi,0);
        build(1,1);
        BuildTree(1,id,1);
        int ans;
        for(i=1;i<=p;i++){
            scanf("%s",str);
            if(str[0]=='I'){
                scanf("%d%d%d",&u,&v,&val);
                calc(u,v,val);
            }
            else if(str[0]=='D'){
                scanf("%d%d%d",&u,&v,&val);
                calc(u,v,-val);
            }else {
                scanf("%d",&u);
                ans=getans(w[u],1);
                printf("%d\n",num[u]+ans);
            }
        }
    }
    return 0;
}

 

posted @ 2013-09-13 13:57  fangguo  阅读(132)  评论(0编辑  收藏  举报