51nod1199:Money out of Thin Air(线段树)

  按dfs序一个一个加入线段树,可以让任何一颗子树的节点在线段树中连续,于是就可以用线段树维护整棵树了

  和树剖的思想是一样的,大概一眼就看出来了,但是写了两个半天(躺

  总结:记住以后写完数据结构或者数字比较大的题用搜索搜一下乘号想想会不会爆long long TAT

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=500010,mod=1e9+7;
struct poi{int too,pre;}e[maxn];
struct zs{ll sum,delta;}tree[maxn];
int n,m,x,y,z,tot,cnt;
int last[maxn],a[maxn],l[maxn],r[maxn],w[maxn];
char s[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
inline void dfs(int x,int fa)
{
    a[++cnt]=w[x];l[x]=cnt;
    for(int i=last[x];i;i=e[i].pre)
    if(e[i].too!=fa)dfs(e[i].too,x);
    r[x]=cnt;
}
inline void pushup(int x){tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;}
inline void pushdown(int x,int l,int r)
{
    if(!tree[x].delta)return;
    tree[x<<1].delta+=tree[x].delta;
    tree[x<<1|1].delta+=tree[x].delta;
    int mid=(l+r)>>1;
    tree[x<<1].sum+=tree[x].delta*(mid-l+1);
    tree[x<<1|1].sum+=tree[x].delta*(r-mid);
    tree[x].delta=0;
}
inline void build(int x,int l,int r)
{
    if(l==r){tree[x].sum=a[l];return;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid);build(x<<1|1,mid+1,r);
    pushup(x);
}
inline void insert(int x,int l,int r,int cx,int sd,int delta)
{
    if(l==r){if(tree[x].sum<sd)tree[x].sum+=delta;return;}
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(cx<=mid)insert(x<<1,l,mid,cx,sd,delta);
    else insert(x<<1|1,mid+1,r,cx,sd,delta);
    pushup(x);
}
inline void add(int x,int l,int r,int cl,int cr,int delta)
{
    if(cl<=l&&r<=cr){tree[x].delta+=delta,tree[x].sum+=1ll*delta*(r-l+1);return;}
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(cl<=mid)add(x<<1,l,mid,cl,cr,delta);
    if(cr>mid)add(x<<1|1,mid+1,r,cl,cr,delta);
    pushup(x);
}
inline ll query(int x,int l,int r,int cl,int cr)
{
    if(cl<=l&&r<=cr)return tree[x].sum;
    pushdown(x,l,r);
    int mid=(l+r)>>1;ll res=0;
    if(cl<=mid)res+=query(x<<1,l,mid,cl,cr);
    if(cr>mid)res+=query(x<<1|1,mid+1,r,cl,cr);
    return res;
}
int main()
{
    read(n);read(m);
    for(int i=2;i<=n;i++)
    {
        read(x);read(w[i]);
        x++;add(x,i);
    }
    dfs(1,0);build(1,1,cnt);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s+1);read(x);read(y);read(z);x++;
        if(s[1]=='S')insert(1,1,cnt,l[x],y,z);
        else if(query(1,1,cnt,l[x],r[x])<1ll*y*(r[x]-l[x]+1))add(1,1,cnt,l[x],r[x],z);
    }
    for(int i=1;i<=n;i++)printf("%lld
",query(1,1,cnt,l[i],l[i]));
}
View Code
原文地址:https://www.cnblogs.com/Sakits/p/7364869.html