codeforces#1136E. Nastya Hasn't Written a Legend(二分+线段树)

题目链接:

http://codeforces.com/contest/1136/problem/E

题意:

初始有a数组和k数组

有两种操作,一,求l到r的区间和,二,$a_ipm x$

并且会有一个连锁反应

$$whileleft ( a_{i+1}<a_i+k_i ight )a_{i+1}=a_i+k_i,i++ $$

数据范围:

$2 leq n leq 10^{5}$
$-10^{9} leq a_i leq 10^{9}$
$-10^{6} leq k_i leq 10^{6}$
$1 leq q leq 10^{5}$
$1 leq i leq n$,$0 leq x leq 10^{6}$
$1 leq l leq r leq n$



分析: 

 对于每次修改,我们可以用二分查找到连锁的末尾。

而对于一个被修改后的区间$(i,r)$的元素$a_x$,它由两部分组成$a_x=a_i+sum_{j=i}^{x-1}k_j$

两部分的值都可以轻易算出,然后用两颗线段树分别记录两部分的区间和(一颗线段树也行)。

用到前缀和的前缀和,还有懒惰标记

具体实现见ac代码

 ac代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
const ll INF=1e18;
ll sum1[maxn],sum2[maxn],treea[4*maxn],treeb[4*maxn],lazya[4*maxn],lazyb[4*maxn];
int a[maxn];
void bulida(int l,int r,int rt)
{
    int md=(r+l)/2;
    if(r==l)
    {
        treea[rt]=a[l];
        return;
    }
    bulida(l,md,rt*2);
    bulida(md+1,r,rt*2+1);
    treea[rt]=treea[rt*2]+treea[rt*2+1];
}
void pushdowna(int l,int r,int rt)
{
    int md=(l+r)/2;
    if(lazya[rt]!=-INF)
    {
        treea[rt*2]=(md-l+1)*lazya[rt];
        treea[rt*2+1]=(r-md-1+1)*lazya[rt];
        lazya[rt*2]=lazya[rt*2+1]=lazya[rt];
        lazya[rt]=-INF;
    }
}
ll quera(int l,int r,int nowl,int nowr,int rt)
{
    if(r<nowl||l>nowr)return 0;
    int md=(nowr+nowl)/2;
    if(l<=nowl&&r>=nowr)return treea[rt];
    pushdowna(nowl,nowr,rt);
    return quera(l,r,nowl,md,rt*2)+quera(l,r,md+1,nowr,rt*2+1);
}
void updataa(ll x,int l,int r,int nowl,int nowr,int rt)
{
    if(r<nowl||l>nowr)return ;
    int md=(nowr+nowl)/2;
    if(l<=nowl&&r>=nowr)
    {
        treea[rt]=(nowr-nowl+1)*x;
        lazya[rt]=x;
        return ;
    }
    pushdowna(nowl,nowr,rt);
    updataa(x,l,r,nowl,md,rt*2);
    updataa(x,l,r,md+1,nowr,rt*2+1);
    treea[rt]=treea[rt*2]+treea[rt*2+1];
}

void pushdownb(int l,int r,int rt)
{
    int md=(l+r)/2;
    if(lazyb[rt]!=-INF)
    {
        treeb[rt*2]=sum2[md-1]-sum2[l-2]+(l-md-1)*sum1[lazyb[rt]-1];
        treeb[rt*2+1]=sum2[r-1]-sum2[md+1-2]+(md+1-r-1)*sum1[lazyb[rt]-1];
        lazyb[rt*2]=lazyb[rt*2+1]=lazyb[rt];
        lazyb[rt]=-INF;
    }
}
void updatabb(ll x,int pos,int nowl,int nowr,int rt)
{
    int md=(nowr+nowl)/2;
    if(nowl==nowr)
    {
        treeb[rt]=x;
        return ;
    }
    pushdownb(nowl,nowr,rt);
    if(pos>=md+1)updatabb(x,pos,md+1,nowr,rt*2+1);
    else updatabb(x,pos,nowl,md,rt*2);
    treeb[rt]=treeb[rt*2]+treeb[rt*2+1];
}
ll querb(int l,int r,int nowl,int nowr,int rt)
{
    if(r<nowl||l>nowr)return 0;
    int md=(nowr+nowl)/2;
    if(l<=nowl&&r>=nowr)return treeb[rt];
    pushdownb(nowl,nowr,rt);
    return querb(l,r,nowl,md,rt*2)+querb(l,r,md+1,nowr,rt*2+1);
}
void updatab(ll x,int l,int r,int nowl,int nowr,int rt)
{
    if(r<nowl||l>nowr)return ;
    int md=(nowr+nowl)/2;
    if(l<=nowl&&r>=nowr)
    {
        treeb[rt]=sum2[nowr-1]-sum2[nowl-2]+(nowl-nowr-1)*sum1[x-1];
        lazyb[rt]=x;
        return ;
    }
    pushdownb(nowl,nowr,rt);
    updatab(x,l,r,nowl,md,rt*2);
    updatab(x,l,r,md+1,nowr,rt*2+1);
    treeb[rt]=treeb[rt*2]+treeb[rt*2+1];
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    for(int i=1; i<=n-1; i++)
    {
        int x;
        scanf("%d",&x);
        sum1[i]=sum1[i-1]+x;
        sum2[i]=sum2[i-1]+sum1[i];
    }
    for(int i=0; i<4*maxn; i++)lazya[i]=lazyb[i]=-INF;
    bulida(1,n,1);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        getchar();
        char key;
        scanf("%c",&key);
        if(key=='s')
        {
            int l,r;
            scanf("%d %d",&l,&r);
            printf("%lld
",quera(l,r,1,n,1)+querb(l,r,1,n,1));
        }
        else if(key=='+')
        {
            ll x,add;
            scanf("%lld %lld",&x,&add);
            add=quera(x,x,1,n,1)+querb(x,x,1,n,1)+add;
            int st=x,en=n;
            while(st!=en)
            {
                int md=(st+en)/2;
                if(sum1[md+1-1]-sum1[x-1]+add>=querb(md+1,md+1,1,n,1)+quera(md+1,md+1,1,n,1))st=md+1;
                else en=md;
            }
            updataa(add,x,st,1,n,1);
            updatab(x,x+1,st,1,n,1);
            updatabb(0,x,1,n,1);
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/carcar/p/10758424.html