• 【bzoj4293】[PA2015]Siano【线段树】


    传送门
    线段树模板题,需要满足区间add和区间set,维护区间和及区间最大值。
    有一个非常鬼畜的pushdown,注意必须先处理set标记,再处理add标记,set后要清空add标记。
    直接continue结果忘记赋值造成WA的悲剧啊!

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=500005;
    int n,m,w;
    ll d,b,ld,tmp,a[N],s[N],addv[N*4],setv[N*4],maxv[N*4],sumv[N*4];
    void pushdown(int o,int l,int r){
        int mid=(l+r)/2;
        if(~setv[o]){
            addv[o*2]=0;
            addv[o*2+1]=0;
            setv[o*2]=setv[o];
            setv[o*2+1]=setv[o];
            maxv[o*2]=setv[o];
            maxv[o*2+1]=setv[o];
            sumv[o*2]=setv[o]*(mid-l+1);
            sumv[o*2+1]=setv[o]*(r-mid);
            setv[o]=-1;
        }
        if(addv[o]){
            addv[o*2]+=addv[o];
            addv[o*2+1]+=addv[o];
            maxv[o*2]+=addv[o]*a[mid];
            maxv[o*2+1]+=addv[o]*a[r];
            sumv[o*2]+=addv[o]*(s[mid]-s[l-1]);
            sumv[o*2+1]+=addv[o]*(s[r]-s[mid]);
            addv[o]=0;
        }
    }
    void get(int o,int l,int r,ll v){
        if(l==r){
            w=l;
            return;
        }
        pushdown(o,l,r);
        int mid=(l+r)/2;
        if(maxv[o*2]>=v){
            get(o*2,l,mid,v);
        }else if(maxv[o*2+1]>=v){
            get(o*2+1,mid+1,r,v);
        }else{
            w=0;
        }
    }
    ll query(int o,int l,int r,int L,int R){
        if(L<=l&&R>=r){
            return sumv[o];
        }
        pushdown(o,l,r);
        int mid=(l+r)/2;
        ll res=0;
        if(L<=mid){
            res+=query(o*2,l,mid,L,R);
        }
        if(R>mid){
            res+=query(o*2+1,mid+1,r,L,R);
        }
        return res;
    }
    void set(int o,int l,int r,int L,int R,ll v){
        if(L<=l&&R>=r){
            addv[o]=0;
            setv[o]=v;
            maxv[o]=v;
            sumv[o]=v*(r-l+1);
            return;
        }
        pushdown(o,l,r);
        int mid=(l+r)/2;
        if(L<=mid){
            set(o*2,l,mid,L,R,v);
        }
        if(R>mid){
            set(o*2+1,mid+1,r,L,R,v);
        }
        maxv[o]=max(maxv[o*2],maxv[o*2+1]);
        sumv[o]=sumv[o*2]+sumv[o*2+1];
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++){
            s[i]=s[i-1]+a[i];
        }
        memset(setv,-1,sizeof(setv));
        for(int i=1;i<=m;i++){
            scanf("%lld%lld",&d,&b);
            tmp=d-ld;
            addv[1]+=tmp;
            maxv[1]+=tmp*a[n];
            sumv[1]+=tmp*s[n];
            if(b>maxv[1]){
                puts("0");
                ld=d;
                continue;
            }
            get(1,1,n,b);
            printf("%lld
    ",query(1,1,n,w,n)-b*(n-w+1));
            set(1,1,n,w,n,b);
            ld=d;
        }
        return 0;
    }
  • 相关阅读:
    Spring 配置数据源的几种方式
    Java List 数据操作
    javascript 数组方法解析
    jQuery 获取页面元素的属性值
    表格列排序
    优秀资源的收集
    Java 集合介绍
    二进制、八进制、十进制、十六进制的转换
    Nginx配置
    Nginx安装
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476896.html
Copyright © 2020-2023  润新知