码迷,mamicode.com
首页 > 其他好文 > 详细

CF1136E Nastya Hasn't Written a Legend(线段树)

时间:2019-07-01 21:45:46      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:har   getc   type   nbsp   main   前缀   线段树   define   二分   

还能说什么呢,简直太妙了。

$$a_{i+1}<a_i+k_i$$

$$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i+k_i-k_i-k_{i-1}-\cdots-k_1$$

$$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i-k_{i-1}-\cdots-k_1$$

令 $k$ 的前缀和为 $kpre$。

$$a_{i+1}-kpre_i<a_i-kpre_{i-1}$$

令 $b_i=a_i-kpre_{i-1}$。

$$b_{i+1}<b_i$$

也就是 $b$ 应该是单调不降的。

询问,经典操作。注意要加回一些 $kpre$。具体要再开一个 $kpre$ 的前缀和 $kprepre$。

修改,可以线段树上二分,找到最后一个 $\le val$ 的值,区间覆盖即可。

时间复杂度 $O(n+q\log n)$。

技术图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100010;
const ll INF=9e18;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<0 || ch>9) f|=ch==-,ch=getchar();
    while(ch>=0 && ch<=9) x=x*10+ch-0,ch=getchar();
    return f?-x:x;
}
int n,q,a[maxn],k[maxn];
ll kpre[maxn],kprepre[maxn],b[maxn],sum[maxn*4],L[maxn*4],R[maxn*4],cov[maxn*4];
char op[5];
inline int pushup(int o){
    sum[o]=sum[o<<1]+sum[o<<1|1];
    L[o]=L[o<<1];
    R[o]=R[o<<1|1];
}
inline void cover(int o,int l,int r,ll x){
    sum[o]=(r-l+1)*x;
    L[o]=R[o]=cov[o]=x;
}
inline void pushdown(int o,int l,int r){
    if(cov[o]!=-INF){
        int mid=(l+r)>>1;
        cover(lson,cov[o]);
        cover(rson,cov[o]);
        cov[o]=-INF;
    }
}
void build(int o,int l,int r){
    cov[o]=-INF;
    if(l==r) return void(sum[o]=L[o]=R[o]=b[l]);
    pushdown(o,l,r);
    int mid=(l+r)>>1;
    build(lson);build(rson);
    pushup(o);
}
ll query(int o,int l,int r,int ql,int qr){
    if(l>=ql && r<=qr) return sum[o];
    pushdown(o,l,r);
    int mid=(l+r)>>1;
    ll s=0;
    if(mid>=ql) s+=query(lson,ql,qr);
    if(mid<qr) s+=query(rson,ql,qr);
    return s;
}
void update(int o,int l,int r,int p,ll v){
    if(r<p || L[o]>v) return;
    if(l>=p && R[o]<=v) return cover(o,l,r,v);
    pushdown(o,l,r);
    int mid=(l+r)>>1;
    update(lson,p,v);update(rson,p,v);
    pushup(o);
}
int main(){
    n=read();
    FOR(i,1,n) a[i]=read();
    FOR(i,1,n-1) k[i]=read();
    FOR(i,1,n-1) kpre[i]=kpre[i-1]+k[i];
    FOR(i,1,n-1) kprepre[i]=kprepre[i-1]+kpre[i];
    FOR(i,1,n) b[i]=a[i]-kpre[i-1];
    build(1,1,n);
    q=read();
    while(q--){
        scanf("%s",op+1);
        int x=read(),y=read();
        if(op[1]==+) update(1,1,n,x,query(1,1,n,x,x)+y);
        else cout<<query(1,1,n,x,y)+kprepre[y-1]-kprepre[max(0,x-2)]<<endl;
    }
}
View Code

 

CF1136E Nastya Hasn't Written a Legend(线段树)

标签:har   getc   type   nbsp   main   前缀   线段树   define   二分   

原文地址:https://www.cnblogs.com/1000Suns/p/11116677.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!