hdu 3966 Aragorn's Story 树链剖分

来源:互联网 发布:网络威胁别人什么罪 编辑:程序博客网 时间:2024/05/16 17:43

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966

题意:

给定一棵树,且给定这棵树上各个点的权值,有以下三种操作:I x y z:将点x到点y的路径上的所有点加上z;D x y z:将点x到点y的路径上的所有点减去z;Q x:查询点x的权值。

树链剖分裸题,先剖分后用线段树维护。
手动开栈!手动开栈!手动开栈!

#pragma comment(linker, "/STACK:1024000000,1024000000") 

关于树链剖分,我认为它是将一棵树,按照重边分成了一堆的链,之后将这些链首尾相连,之后就用各种数据结构去搞一搞就可以了。

Code
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 50010#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;struct node{    int next,to;};node Edge[N<<1];int n,m,q,tot,QT;int a[N];int dfn[N],son[N],fa[N],size[N];int w[N],top[N];int pp[N];int f[N<<2],sum[N<<2];int head[N];void clear(){    memset(head,0,sizeof(head));    memset(son,0,sizeof(son));    memset(dfn,0,sizeof(dfn));    memset(fa,0,sizeof(fa));    memset(size,0,sizeof(size));    memset(w,0,sizeof(w));    memset(top,0,sizeof(top));    memset(pp,0,sizeof(pp));    tot=0;    QT=0;}void addedge(int x,int y){    Edge[++tot].next=head[x];    Edge[tot].to=y;    head[x]=tot;}void dfs1(int u,int root,int deep){    fa[u]=root;    dfn[u]=deep;    size[u]=1;    for(int i=head[u];i;i=Edge[i].next)    {        int to=Edge[i].to;        if(to==root)continue;        dfs1(to,u,deep+1);        size[u]+=size[to];        if(size[to]>size[son[u]])son[u]=to;    }}void dfs2(int u,int tp){    top[u]=tp;    w[u]=++QT;    pp[QT]=u;    if(!son[u])return ;    dfs2(son[u],tp);    for(int i=head[u];i;i=Edge[i].next)    {        int to=Edge[i].to;        if(to==fa[u]||to==son[u])continue;        dfs2(to,to);    }}void PushUp(int rt){    f[rt]=max(f[rt<<1],f[rt<<1|1]);}void PushDown(int rt){    if(!sum[rt])return ;    sum[rt<<1]+=sum[rt];    sum[rt<<1|1]+=sum[rt];    f[rt<<1]+=sum[rt];    f[rt<<1|1]+=sum[rt];    sum[rt]=0;}void build(int l,int r,int rt){    sum[rt]=0;    if(l==r)    {        f[rt]=a[pp[l]];        return ;    }    int mid=(l+r)>>1;    build(lson);    build(rson);    PushUp(rt);}int query(int l,int r,int rt,int x){    if(l==r)return f[rt];    PushDown(rt);    int mid=(l+r)>>1;    int ans=0;    if(mid>=x)ans=query(lson,x);    else ans=query(rson,x);    PushUp(rt);    return ans;}void updata(int l,int r,int rt,int L,int R,int c){    if(l>=L&&r<=R)    {        f[rt]+=c;        sum[rt]+=c;        return ;    }    PushDown(rt);    int mid=(l+r)>>1;    if(mid>=L)updata(lson,L,R,c);    if(mid<R) updata(rson,L,R,c);    PushUp(rt);}void change(int x,int y,int cnt){    while(top[x]!=top[y])    {        if(dfn[top[x]]<dfn[top[y]])swap(x,y);        updata(1,n,1,w[top[x]],w[x],cnt);        x=fa[top[x]];    }    if(dfn[x]>dfn[y])swap(x,y);    updata(1,n,1,w[x],w[y],cnt);}int main(){    while(~scanf("%d%d%d",&n,&m,&q))    {        clear();        for(int i=1;i<=n;i++)scanf("%d",&a[i]);        for(int i=1;i<=m;i++)        {            int x,y;            scanf("%d%d",&x,&y);            addedge(x,y);            addedge(y,x);        }        dfs1(1,0,1);        dfs2(1,1);        build(1,n,1);        for(int i=1;i<=q;i++)        {            char s[10];            int x,y,z;            scanf("%s",s);            if(s[0]=='Q')            {                scanf("%d",&x);                printf("%d\n",query(1,n,1,w[x]));            }else            {                scanf("%d%d%d",&x,&y,&z);                if(s[0]=='D')z=-z;                change(x,y,z);            }        }    }    return 0;}
0 0
原创粉丝点击