HDU 3966 Aragorn's Story (树链剖分第一题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966

#include<bits/stdc++.h>
using namespace std;
const int  maxn =1e5+5;
/*
题目大意:就是在一颗树上维护,
两点间路径的权重修改,查询单点权值.

对于树上路径的维护和修改,
树链剖分的话最重要的还是一种分块的思想,
把链分成重轻链,然后把点映射到树状数组中,
再单独封装修改操作,这样修改的复杂度就被均摊了。
代码太模板了,看看就好,我压缩和注释的感觉还可以。
*/
///链式前向星存边
struct edge{int u,nxt;}e[maxn<<1];
int head[maxn],tot;
void init(){memset(head,-1,sizeof(head));tot=0;}
void add(int x,int y){e[tot]=edge{y,head[x]};head[x]=tot++;}
///两遍DFS,第一遍确定各个数组,第二遍哈希边
int siz[maxn],dep[maxn],fa[maxn],son[maxn];
void dfs1(int u,int pre,int d)
{
    siz[u]=1,fa[u]=pre,dep[u]=d;
    for(int i=head[u];~i;i=e[i].nxt)
    {
        int v=e[i].u;
        if(v==pre) continue;
        dfs1(v,u,d+1);
        siz[u]+=siz[v];
        if(son[u]==-1||siz[v]>siz[son[u]])  son[u]=v;
    }
}
///重新建立映射,方便丢到数据结构中
int p[maxn],fp[maxn],top[maxn];///双射
void dfs2(int u,int sp)
{
    top[u]=sp,p[u]=tot++,fp[p[u]]=u;///建立双射,建立父节点
    if(son[u]==-1) return ;
    dfs2(son[u],sp);///建立链的关系
    for(int i=head[u];~i;i=e[i].nxt)
    {
        int v=e[i].u;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
///树状数组数据结构维护树上操作
int bit[maxn<<1];
int lowbit(int x){return x&(-x);}
void refresh(int x,int d){for(;x<maxn;bit[x]+=d,x+=lowbit(x));}
int sum(int x){int ret=0;for(;x>0;ret+=bit[x],x-=lowbit(x));return ret;}
///读入数据域
int n,m,q,x,y,z;
int v[maxn];
char op[10];
///修改路径上的权重
void update(int u,int v,int val)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(u,v);
        }
        refresh(p[u]+1,-val),refresh(p[f1],val);
        u=fa[f1],f1=top[u];
    }
    if(dep[u]>dep[v]) swap(u,v);
    refresh(p[u],val),refresh(p[v]+1,-val);
}

int main()
{
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        init();///初始化
        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        memset(son,-1,sizeof(son));///又重新初始化
        memset(bit,0,sizeof(bit));tot=1;
        dfs1(1,-1,0),dfs2(1,1);
        for(int i=1;i<=n;i++) refresh(p[i],v[i]),refresh(p[i]+1,-v[i]);
        for(int i=0;i<q;i++)
        {
            scanf("%s",op);
            if(op[0]=='Q'){scanf("%d",&x);printf("%d\n",sum(p[x]));}
            else
            {
                scanf("%d%d%d",&x,&y,&z);
                if(op[0]=='D') z=-z;
                update(x,y,z);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82941700