HDU-3966-Aragorn's Story(樹鏈剖分)

鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3966

題意:

給出一棵樹,

I C1 C2 K: 把C1與C2的路徑上的所有點權值加上K

D C1 C2 K:把C1與C2的路徑上的所有點權值減去K

Q C:查詢節點編號爲C的權值


題解:

樹鏈剖分

CODE:


#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define bug cout<<"bug"<<endl
const int MAXN = 50007;
const int MOD = 1e9 + 9;
int n,m,q;
int a[MAXN],deep[MAXN],siz[MAXN],far[MAXN],
        son[MAXN],hit[MAXN],rev[MAXN],top[MAXN];
int num[MAXN],head[MAXN<<2],ind,sum[MAXN<<2],lazy[MAXN<<2];
struct node
{
    int v,next;
}edge[MAXN<<2];
void add_edge(int u, int v)
{
    edge[ind].v=v;
    edge[ind].next=head[u];
    head[u]=ind++;
}
int Dep2;
void dfs_size(int u, int fa,int d)
{
    deep[u]=++d;
    siz[u]=1;
    far[u]=fa;
    for(int i=head[u]; i+1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(v!=fa)
        {
            dfs_size(v,u,d);
            siz[u]+=siz[v];
            if(!son[u] || siz[v]>siz[ son[u] ])
                son[u]=v;
        }
    }
}
void dfs_list(int u, int p)
{
    top[u]=p;
    hit[u]=++Dep2;
    rev[Dep2]=u;
    if(!son[u])return ;
    dfs_list(son[u],p);
    for(int i=head[u]; i+1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(v!=son[u] && v!=far[u])
            dfs_list(v,v);
    }
}
void push(int poi)
{
    if(lazy[poi])
    {
        lazy[poi<<1]+=lazy[poi];
        lazy[poi<<1^1]+=lazy[poi];
        lazy[poi]=0;
    }
}
void build(int poi, int l, int r)
{
    lazy[poi]=0;
    if(l==r)
    {
        sum[poi]=num[ rev[l] ];
        return ;
    }
    int mid=(l+r)>>1;
    sum[poi]=0;
    build(poi<<1, l, mid);
    build(poi<<1^1, mid+1, r);
}
void add(int poi, int l, int r, int val, int a, int b)
{

    if(a<=l && r<=b){lazy[poi]+=val;return;}
    push(poi);
    int mid=(l+r)>>1;
    if(mid>=a)add(poi<<1,l,mid,val,a,b);
    if(b>mid)add(poi<<1^1,mid+1,r,val,a,b);
}
void find_list(int a, int b, int val)
{
    while(top[a]!=top[b])
    {
        if(hit[ top[a] ] > hit[ top[b] ])swap(a,b);
        add(1,1,n,val,hit[ top[b] ],hit[b]);
        b=far[ top[b] ];
    }
    if(deep[a] > deep[b])swap(a,b);
    add(1,1,n,val,hit[a],hit[b]);
}
int query(int poi, int l, int r, int p)
{
    if(l==r)return sum[poi]+lazy[poi];
    push(poi);
    int mid=(l+r)>>1;
    if(mid>=p)return query(poi<<1,l,mid,p);
    return query(poi<<1^1,mid+1,r,p);
}
int main()
{

    char str[3];
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
        int a,b,c;
        Dep2=ind=0;
        memset(head,-1,sizeof(head));
        memset(son,0,sizeof(son));
        for(int i=1; i<=n; ++i)
            scanf("%d",&num[i]);
        for(int i=1; i<=m; ++i)
        {
            scanf("%d%d",&a,&b);
            add_edge(a,b);
            add_edge(b,a);
        }
        dfs_size(1,0,0);
        dfs_list(1,1);
        build(1,1,n);
        for(int i=0; i<q; ++i)
        {
            scanf("%s",str);
            if(str[0]=='Q')
            {
                scanf("%d",&a);
                printf("%d\n",query(1,1,n,hit[a]));
            }
            else
            {
                scanf("%d%d%d",&a,&b,&c);
                if(str[0]=='D')c=-c;
                find_list(a,b,c);
            }
        }
    }
}
/*
3 2 5
1 2 3
2 1
2 3
I 1 3 5
Q 2
D 1 2 2
Q 1
Q 3
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章