题目链接:

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

题意:

初始有a数组和k数组

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

并且会有一个连锁反应

$$while\left ( a_{i+1}<a_i+k_i \right )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\n",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;
}

  

codeforces#1136E. Nastya Hasn't Written a Legend(二分+线段树)的更多相关文章

  1. cf1136E. Nastya Hasn't Written a Legend(二分 线段树)

    题意 题目链接 Sol yy出了一个暴躁线段树的做法. 因为题目保证了 \(a_i + k_i <= a_{i+1}\) 那么我们每次修改时只需要考虑取max就行了. 显然从一个位置开始能影响到 ...

  2. Codeforces 1136E - Nastya Hasn't Written a Legend - [线段树+二分]

    题目链接:https://codeforces.com/problemset/problem/1136/E 题意: 给出一个 $a[1 \sim n]$,以及一个 $k[1 \sim (n-1)]$, ...

  3. Codeforces 1136E Nastya Hasn't Written a Legend 线段树

    vp的时候没码出来.. 我们用set去维护, 每一块区域, 每块区域内的元素与下一个元素的差值刚好为ki,每次加值的时候我们暴力合并, 可以发现我们最多合并O(n)次. 然后写个线段树就没了. #in ...

  4. Codeforces 1136E Nastya Hasn't Written a Legend (线段树教做人系列)

    题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后, ...

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

    还能说什么呢,简直太妙了. $$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- ...

  6. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  7. Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树)

    Codeforces Round #620 F2. Animal Observation (hard version) (dp + 线段树) 题目链接 题意 给定一个nm的矩阵,每行取2k的矩阵,求总 ...

  8. Codeforces Round #292 (Div. 1) C. Drazil and Park 线段树

    C. Drazil and Park 题目连接: http://codeforces.com/contest/516/problem/C Description Drazil is a monkey. ...

  9. Codeforces Round #254 (Div. 1) C. DZY Loves Colors 线段树

    题目链接: http://codeforces.com/problemset/problem/444/C J. DZY Loves Colors time limit per test:2 secon ...

随机推荐

  1. Hadoop系列008-HDFS的数据流

    本人微信公众号,欢迎扫码关注! HDFS的数据流 1 HDFS写数据流程 1.1 剖析文件写入 1)客户端向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在. 2) ...

  2. GitHub的Repository权限将public转为private

    2019年1月7日,GitHub CEO Nat Friedman 于官方博客公开发文,称“New year, new GitHub”,宣布从此将免费无限地为普通用户提供私有仓库服务. 因此,我们可以 ...

  3. eclipse升级Android SDK Tool版本到25.2.5后运行项目报错Unable to build: the file dx.jar was not loaded from the SDK folder

    概述 由于最近通过SDK-Manager更新了build-tools,当要用到dx.jar这个包时,自动调用最新版本Android SDK build-tools中dx.jar,但是运行android ...

  4. XML的创建、解析-C语言

    前言:今天在做一个小项目时,客户要求的xml,跟现在有系统要求的不一样,所以要自己重新写函数支持返回,进行简单总结,希望对大家有所帮助. 首先,使用xml函数需要链上动态库libxml2,需要在电脑上 ...

  5. 版本控制工具——Git常用操作(上)

    本文由云+社区发表 作者:工程师小熊 摘要:用了很久的Git和svn,由于总是眼高手低,没能静下心来写这些程序员日常开发最常用的知识点.现在准备开一个专题,专门来总结一下版本控制工具,让我们从git开 ...

  6. 1.2环境安装「深入浅出ASP.NET Core系列」

    官网 在介绍安装环境之前,先介绍周边信息,比如微软net官网. https://www.microsoft.com/net 这个网站是学习微软技术栈比较权威的地方,包括环境下载,学习,架构,文档,社区 ...

  7. DSAPI 短域名服务

    有时,需要将长域名转换为短域名,或是为了减少字符量,或是为了隐藏真实网址.在DSAPI中,集成了EPS-GS的短域名接口.该功能需要联接互联网,从EPS服务器获取. 代码 DSAPI.网络.短域名服务 ...

  8. .Net 委托 delegate 学习

    一.什么是委托: 委托是寻址方法的.NET版本,使用委托可以将方法作为参数进行传递.委托是一种特殊类型的对象,其特殊之处在于委托中包含的只是一个活多个方法的地址,而不是数据.   二.使用委托: 关键 ...

  9. 2018/1.6 Javascript 继承和克隆

    这种写法不是对象克隆,就是把obj的内存地址赋给obj2 通过 for in 克隆 不管公有还是私有的都克隆成私有的. js提供了一个克隆方法 objct.create() var obj2=obje ...

  10. 微信小程序中通过腾讯地图进行逆地址解析报错message: "请求来源未被授权, 此次请求来源域名:servicewechat.com"

    在小程序中获取定位具体信息时,不要配置腾讯地图中的WebServiceAPI中的域名白名单什么的,域名配置直接在小程序后台中配置(就是这个货https://apis.map.qq.com), 千万千万 ...