HDU-3966-Aragorn's Story(树链剖分)

来源:互联网 发布:做淘宝直通车和刷流量 编辑:程序博客网 时间:2024/05/23 02:05

链接: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"<<endlconst 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 51 2 32 12 3I 1 3 5Q 2D 1 2 2Q 1Q 3*/


0 0
原创粉丝点击