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;

}

 

你可能感兴趣的:(HDU)