hdu 3966 树链剖分 模板题

来源:互联网 发布:邵氏孤儿 知乎 编辑:程序博客网 时间:2024/06/06 12:20

题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值

分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易爆栈,所以在代码
前面加上:#pragma comment(linker, “/STACK:1024000000,1024000000”)进行手动扩栈。

下面有代码和注释

纯模板:

#pragma comment(linker,"/STACK:1024000000,1024000000")#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <vector>using namespace std;const int N=50010;int n,m,Q;int tim;int num[N],siz[N],top[N],son[N];int dep[N],tid[N],ran[N],fa[N];int head[N],to[2*N],nex[2*N],edge;void init(){    memset(head,-1,sizeof(head));    memset(son,-1,sizeof(son));    tim=0;    edge=0;}void addedge(int u,int v){    to[edge]=v,nex[edge]=head[u],head[u]=edge++;    to[edge]=u,nex[edge]=head[v],head[v]=edge++;}void dfs1(int u,int father,int d){    dep[u]=d;    fa[u]=father;    siz[u]=1;    for(int i=head[u];~i;i=nex[i])    {        int v=to[i];        if(v!=father)        {            dfs1(v,u,d+1);            siz[u]+=siz[v];            if(son[u]==-1||siz[v]>siz[son[u]])                son[u]=v;        }    }}void dfs2(int u,int tp){    top[u]=tp;    tid[u]=++tim;    ran[tid[u]]=u;    if(son[u]==-1) return ;    dfs2(son[u],tp);    for(int i=head[u];~i;i=nex[i])    {        int v=to[i];        if(v!=son[u]&&v!=fa[u])            dfs2(v,v);    }}#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1int sum[4*N],col[4*N];void PushUP(int rt){    sum[rt]=max(sum[rt<<1],sum[rt<<1]|1);}void PushDown(int rt,int m){    if(col[rt])    {        col[rt<<1]+=col[rt];        col[rt<<1|1]+=col[rt];        sum[rt<<1]+=(m-(m>>1))*col[rt];        sum[rt<<1|1]+=(m>>1)*col[rt];        col[rt]=0;    }}void Build(int l,int r,int rt){    col[rt]=0;    if(l==r)    {        sum[rt]=num[ran[l]];        return ;    }    int mid=(l+r)>>1;    Build(lson);    Build(rson);    PushUP(rt); }void Update(int L,int R,int v,int l,int r,int rt){    if(L<=l&&R>=r)    {        col[rt]+=v;        sum[rt]+=v*(r-l+1);        return ;    }    PushDown(rt,r-l+1);    int mid=(l+r)>>1;    if(L<=mid)    {        Update(L,R,v,lson);    }    if(R>mid)        Update(L,R,v,rson);    PushUP(rt);}int Query(int l,int r,int rt,int val){    if(l==r)    {        return sum[rt];     }    PushDown(rt,r-l+1);    int mid=(l+r)>>1;    int ret=0;    if(val<=mid) ret=Query(lson,val);    else ret=Query(rson,val);    PushUP(rt);    return ret;}void Change(int x,int y,int val){    while(top[x]!=top[y])    {        if(dep[top[x]]<dep[top[y]]) swap(x,y);        Update(tid[top[x]],tid[x],val,1,n,1);        x=fa[top[x]];    }    if(dep[x]>dep[y]) swap(x,y);    Update(tid[x],tid[y],val,1,n,1);}int main(){    char oper[5];    int a,b,c;    while(~scanf("%d%d%d",&n,&m,&Q))    {        init();        for(int i=1;i<=n;i++)            scanf("%d",&num[i]);        for(int i=1;i<=m;i++)        {            scanf("%d%d",&a,&b);            addedge(a,b);        }        dfs1(1,0,0);        dfs2(1,1);        Build(1,n,1);        while(Q--){            scanf("%s",oper);            if(oper[0]=='Q')            {                scanf("%d",&a);                printf("%d\n",Query(1,n,1,tid[a]) );            }            else            {                scanf("%d%d%d",&a,&b,&c);                if(oper[0]=='D') c=-c;                Change(a,b,c);            }        }    }}

代码加注释:

void dfs1(int u,int father,int d)  {      dep[u]=d;      fa[u]=father;      siz[u]=1;      for(int i=head[u];~i;i=next[i])      {          int v=to[i];          if(v!=father)          {              dfs1(v,u,d+1);              siz[u]+=siz[v];              if(son[u]==-1||siz[v]>siz[son[u]])                  son[u]=v;          }      }  }  
原创粉丝点击