51Nod 1199 Money out of Thin Air(dfs序+线段树维护区间和)

来源:互联网 发布:新版淘宝店图片大小 编辑:程序博客网 时间:2024/05/21 09:30

一棵有N个节点的树,每个节点对应1个编号及1个权值,有2种不同的操作。
操作1:S x y z,表示如果编号为x的节点的权值 < y,则将节点x的权值加上z。(Single)
操作2:A x y z,表示如果编号为x的节点以及其所有子节点的权值平均值 < y,则将节点x及其所有子节点的权值加上z。(All)
给出树节点之间的关系,进行M次操作,问所有操作完成后,各个节点的权值为多少?
节点的编号为0 - N - 1,根节点的编号为0,并且初始情况下,根节点的权值也是0。
Input
第1行:2个数N, M,N为节点的数量,M为操作的数量(1 <= N, M <= 50000)。
第2 - N行:每行描述一个节点N[i]的信息,第2行对应编号为1的节点,第N行对应编号为N - 1的节点。具体内容为:每行2个数P[i], W[i]。P[i]为当前节点的父节点的编号,W[i]为当前节点的权值。(0 <= W[i] <= 10^5, P[i] < i)
第N + 1 - N + M行:每行表示一个操作,S x y z或A x y z,(0 <= y, z <= 10^5)。
Output
输出共N行,每行1个数W[i],表示经过M次后,编号为0 - N - 1的节点的权值。
Input示例
4 3
0 10
0 10
1 2
S 0 1 1
A 0 20 1
S 3 2 1
Output示例
2
11
11
3

思路:先跑一遍dfs序,求出每个节点的管辖区间,然后线段是维护即可

#include <bits/stdc++.h>#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("output.txt","w+",stdout);using namespace std;typedef long long ll;const int INF = 0x3f3f3f3f;const int mod = 998244353;const double eps=1e-8;const double Pi=acos(-1.0);const int N= 50005;struct T{    ll val;    ll addmark;} tree[N<<4];struct node{    int to;    ll val;};vector<node> G[N];int L[N],R[N];ll W[N];int n,m,ti;void addedge(int u,int v,ll w){    G[u].push_back((node){v,w});    G[v].push_back((node){u,w});}void init(){    ti=0;    for(int i=0; i<=n; i++)        G[i].clear();    memset(L,0,sizeof(L));    memset(R,0,sizeof(R));    memset(W,0,sizeof(W));    memset(tree,0,sizeof(tree));}void dfs(int u,int w,int per){    L[u]=++ti;    W[ti]=w;    for(int i=0; i<(int)G[u].size(); i++)    {        int v=G[u][i].to;        int c=G[u][i].val;        if(v==per)            continue;        dfs(v,c,u);    }    R[u]=ti;}void build(int root,int l,int r){    if(l==r)        tree[root].val=W[l];    else    {        int mid=(l+r)>>1;        build(root<<1,l,mid);        build(root<<1|1,mid+1,r);        tree[root].val=tree[root<<1].val+tree[root<<1|1].val;    }}void push_down(int root,int l,int r){    if(tree[root].addmark!=0)    {        int mid=(l+r)>>1;        tree[root<<1].addmark+=tree[root].addmark;        tree[root<<1|1].addmark+=tree[root].addmark;        tree[root<<1].val+=tree[root].addmark*(mid-l+1);        tree[root<<1|1].val+=tree[root].addmark*(r-(mid+1)+1);        tree[root].addmark=0;    }}ll query(int root,int l,int r,int b,int e){    if(b>r||e<l)        return 0;    if(b<=l&&r<=e)        return tree[root].val;    push_down(root,l,r);    int mid=(l+r)>>1;    ll sum=0;    sum+=query(root<<1,l,mid,b,e);    sum+=query(root<<1|1,mid+1,r,b,e);    return sum;}void simple_updata(int root,int l,int r,int ind,ll add){    if(l==r)    {        tree[root].val+=add;        return ;    }    int mid=(l+r)>>1;    if(ind<=mid)        simple_updata(root<<1,l,mid,ind,add);    else        simple_updata(root<<1|1,mid+1,r,ind,add);    tree[root].val=tree[root<<1].val+tree[root<<1|1].val;}void interval_updata(int root,int l,int r,int b,int e,ll add){    if(b>r||e<l)        return ;    if(b<=l&&r<=e)    {        tree[root].addmark+=add;        tree[root].val+=add*(r-l+1);        return ;    }    push_down(root,l,r);    int mid=(l+r)>>1;    interval_updata(root<<1,l,mid,b,e,add);    interval_updata(root<<1|1,mid+1,r,b,e,add);    tree[root].val=tree[root<<1].val+tree[root<<1|1].val;}int main(){    init();    scanf("%d %d",&n,&m);    int u;    ll w;    for(int i=1; i<n; i++)    {        scanf("%d %I64d",&u,&w);        addedge(u,i,w);    }    dfs(0,0,-1);//    for(int i=1;i<=n;i++)//        printf("%d\n",W[i]);//    for(int i=0;i<n;i++)//        printf("i:%d L:%d R:%d\n",i,L[i],R[i]);    build(1,1,n);    char ch; int x; ll y,z,num;    for(int i=0;i<m;i++)    {        getchar();        scanf("%c %d %I64d %I64d",&ch,&x,&y,&z);        if(ch=='S')        {            num=query(1,1,n,L[x],L[x]);            //printf("i:%d simple:%I64d\n",i+1,num);            if(num<y)                simple_updata(1,1,n,L[x],z);        }        else if(ch=='A')        {            num=query(1,1,n,L[x],R[x]);            //printf("i:%d interval:%I64d\n",i+1,num);            if((num/(R[x]-L[x]+1))<y)                interval_updata(1,1,n,L[x],R[x],z);        }    }    for(int i=0;i<n;i++)        printf("%I64d\n",query(1,1,n,L[i],L[i]));}
原创粉丝点击