【题解】Siano [PA2015] [Bzoj4293] / Chika 的烦恼

【题解】Siano [PA2015] [Bzoj4293] / Chika 的烦恼

传送门:\(\text{Siano [PA2015]}\) \(\text{[Bzoj4293]}\) \(\text{ / Chika 的烦恼}\)

【分析】

看完题目第一感觉是超哥线段树,但仔细一想发现了个奇妙的性质:由于每次割草只会砍掉最高的那部分,所以生长速度快的草永远都不会比速度慢的矮(顶多一样高)。

可以对速度排个序,那么每次操作的部分一定是一个连续的区间,上线段树即可。

每个区间维护高度和 \(S\)、高度覆盖标记 \(tag\)、时间增量标记 \(add\) 、区间最大高度 \(AR\)(即最右边的草的高度),对于一次操作 \(x_i,y_i\) 在线段树上二分找到第一个大于等于 \(x_i\) 的位置 \(pos\),然后将 \([pos,n]\) 全部覆盖为 \(y_i\),顺便在覆盖的同时计算改变量即为答案。

注意一些实现上的细节:

\(pushdown\) 时优先下放覆盖标记。

区间被覆盖后要清空 \(add\)

有可能找不到大于等于 \(x_i\) 的位置(全部都小于 \(x_i\)),这时要特判。

\(\text{long long}\)

【Code】

#include<algorithm>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=5e5+3;
int n,T,V[N];LL x,y,SV[N];
template<typename T>inline void in(T &x){
    int f=0;x=0;char c=getchar();
    while(c<'0'||c>'9')f|=c=='-',c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x=f?-x:x;
}
struct Sakura2{
    struct Segment_Tree{
        #define pl (p<<1)
        #define pr (p<<1|1)
        #define mid ((L+R)>>1)
        struct QAQ{LL S,AR,add,tag;}tr[N<<2];
        inline void build(Re p,Re L,Re R){
            tr[p].tag=-1;
            if(L==R)return;
            build(pl,L,mid),build(pr,mid+1,R);
        }
        inline void pushup(Re p){
            tr[p].S=tr[pl].S+tr[pr].S,tr[p].AR=tr[pr].AR;
        }
        inline void updata1(Re p,Re L,Re R,LL v){
            tr[p].tag=v,tr[p].S=(LL)(R-L+1)*v,tr[p].AR=v,tr[p].add=0;
        }
        inline void updata2(Re p,Re L,Re R,LL v){
            tr[p].add+=v,tr[p].S+=(LL)(SV[R]-SV[L-1])*v,tr[p].AR+=(LL)V[R]*v;
        }
        inline void pushdown(Re p,Re L,Re R){
            if(tr[p].tag!=-1)updata1(pl,L,mid,tr[p].tag),updata1(pr,mid+1,R,tr[p].tag),tr[p].tag=-1;
            if(tr[p].add)updata2(pl,L,mid,tr[p].add),updata2(pr,mid+1,R,tr[p].add),tr[p].add=0;
        }
        inline int find(Re p,Re L,Re R,LL v){
            if(L==R)return tr[p].S<v?n+1:L;
            pushdown(p,L,R);
            if(tr[pl].AR>=v)return find(pl,L,mid,v);
            else return find(pr,mid+1,R,v);
        }
        inline LL change(Re p,Re L,Re R,Re l,Re r,LL v){
            if(l>r)return 0;
            if(l<=L&&R<=r){LL tmp=tr[p].S;updata1(p,L,R,v);return tmp-tr[p].S;}
            LL ans=0;pushdown(p,L,R);
            if(l<=mid)ans+=change(pl,L,mid,l,r,v);
            if(r>mid)ans+=change(pr,mid+1,R,l,r,v);
            pushup(p);return ans;
        }
    }TR;
    inline void sakura(){
        sort(V+1,V+n+1);
        for(Re i=1;i<=n;++i)SV[i]=SV[i-1]+V[i];
        LL nowT=0;TR.build(1,1,n);
        while(T--){
            in(x),in(y),TR.updata2(1,1,n,x-nowT),nowT=x;
            printf("%lld\n",TR.change(1,1,n,TR.find(1,1,n,y),n,y));
        }
    }
}T2;
int main(){
//    freopen("grass.in","r",stdin);
//    freopen("grass.out","w",stdout);
    in(n),in(T);
    for(Re i=1;i<=n;++i)in(V[i]);
    T2.sakura();
}
posted @ 2020-03-26 14:02  辰星凌  阅读(259)  评论(0编辑  收藏  举报