HDU-3966 Aragorn's Story

树链剖分+树状数组 模板题

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=50000+10;
//树状数组
int lowbit(int x) {return x&(-x);}
int c[N];
int n;
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=c[i];
        i-=lowbit(i);
    }
    return s;
}
void add(int i,int val)
{
    while(i<=n)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
//
struct Edge
{
    int to,nxt;
}edge[N*2];
int first[N],tot;
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].nxt=first[u];
    first[u]=tot++;
}
int top[N]; //树链起点
int fa[N]; //父节点
int deep[N]; //深度
int num[N]; //子树节点个数
int p[N]; //编号
int fp[N];
int son[N]; //重儿子
int pos;
void init()
{
    tot=0;
    memset(first,-1,sizeof(first));
    pos=1; //编号从1开始
    memset(son,-1,sizeof(son));
}
//树链
void dfs1(int u,int pre,int d)
{
    deep[u]=d;
    fa[u]=pre;
    num[u]=1;
    for(int i=first[u];i!=-1;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,u,d+1);
        num[u]+=num[v];
        if(son[u]==-1||num[v]>num[son[u]])
            son[u]=v;
    }
}
void getpos(int u,int sp)
{
    top[u]=sp;
    p[u]=pos++;
    fp[p[u]]=u;
    if(son[u]==-1) return;
    getpos(son[u],sp);
    for(int i=first[u];i!=-1;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v!=son[u]&&v!=fa[u])
            getpos(v,v);
    }
}
void change(int u,int v,int val)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2)
    {
        if(deep[f1]<deep[f2])
        {
            swap(f1,f2);
            swap(u,v);
        }
        add(p[f1],val);  //树状数组改为区间更新,单点查询,以这种方式操作sum(i)即是i点的值
        add(p[u]+1,-val); //等价为p[f1]~p[u]加上val
        u=fa[f1];
        f1=top[u];
    }
    if(deep[u]>deep[v]) swap(u,v);
    add(p[u],val);
    add(p[v]+1,-val);
}
int a[N];
int main()
{
    int m,P;
    int c1,c2,val;
    char s[5];
    while(~scanf("%d%d%d",&n,&m,&P))
    {
        init();
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&c1,&c2);
            addedge(c1,c2);
            addedge(c2,c1);
        }
        dfs1(1,0,0);
        getpos(1,1);
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++)
        {
            add(p[i+1],a[i]);
            add(p[i+1]+1,-a[i]);
        }
        while(P--)
        {
            scanf("%s",s);
            if(s[0]=='I')
            {
                scanf("%d%d%d",&c1,&c2,&val);
                change(c1,c2,val);
            }
            else if(s[0]=='D')
            {
                scanf("%d%d%d",&c1,&c2,&val);
                change(c1,c2,-val);
            }
            else if(s[0]=='Q')
            {
                scanf("%d",&val);
                printf("%d\n",sum(p[val]));
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wl16wzl/article/details/83097080
今日推荐