codeforces 1136E-Nastya Hasn't Written a Legend
传送门:QAQQAQ
题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i]。有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质。比如a[i]加上x之后,a[i + 1]<a[i] + k[i],那么a[i + 1]就变成a[i] + k[i],否则不变。同理,若a[i + 2]小于了现在的a[i + 1] + k[i + 1],那么a[i + 2]也变成a[i + 1] + k[i + 1],一直保持这个性质。第二章操作,询问数组a的区间[l, r]的区间和。
思路:用另一个b数组保存a[i]-(k[1]+k[2]+...+k[i-1]),这样由题意的大小关系可知,b数组是非递减的。所以更新是只需在b[x]加上y用二分找出一段连续的需要被修改的区间即可,为节省时间,k应该用前缀和形式保存。
查询时,只需利用b数组建造线段树并维护,求区间sum并加上之前每个b[i]被减掉的k即可,为节省时间,可以再前缀和k的基础上再加一个前缀和kk。这样查询时只需求query(1,1,n,l,r)+kk[r-1]-kk[l-2]。
注意:b数组只在建线段树时用到,因为后面b不再被更新,需要用query求出最新的b数组里的值; 赋值懒标记tag时一定要赋值成数据无法触碰到的值INF,否则会出现无法pushdown的情况(之前赋值成-1,在第7个点上调了老半天)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
const ll inf=-1e18; ll n,a[N],b[N],k[N],kk[N],m; ll sum[N<<],tag[N<<];
void build(int x,int l,int r)
{
if(l==r)
{
sum[x]=b[l];
return;
}
int mid=(l+r)>>;
build(x+x,l,mid);
build(x+x+,mid+,r);
sum[x]=sum[x+x]+sum[x+x+];
} void push_down(int x,int l,int r)
{
int mid=(l+r)>>;
if(tag[x]==inf) return;
tag[x+x]=tag[x]; tag[x+x+]=tag[x];
sum[x+x]=tag[x]*(mid-l+);
sum[x+x+]=tag[x]*(r-mid);
tag[x]=inf;
} void update(int x,int l,int r,int L,int R,ll val)
{
if(L<=l&&r<=R)
{
tag[x]=val;
sum[x]=val*(r-l+);
return;
}
int mid=(l+r)>>;
push_down(x,l,r);
if(mid>=R) update(x+x,l,mid,L,R,val);
else if(mid<L) update(x+x+,mid+,r,L,R,val);
else
{
update(x+x,l,mid,L,R,val);
update(x+x+,mid+,r,L,R,val);
}
sum[x]=sum[x+x]+sum[x+x+];
} ll query(int x,int l,int r,int L,int R)
{
if(L>R) return ;
if(L<=l&&r<=R) return sum[x];
int mid=(l+r)>>;
push_down(x,l,r);
if(mid>=R) return query(x+x,l,mid,L,R);
else if(mid<L) return query(x+x+,mid+,r,L,R);
else
{
return query(x+x,l,mid,L,R)+query(x+x+,mid+,r,L,R);
}
} int main()
{
for(int i=;i<(N<<);i++) tag[i]=inf;
scanf("%lld",&n);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
for(int i=;i<n;i++) scanf("%lld",&k[i]);
for(int i=;i<n;i++) k[i]+=k[i-];
for(int i=;i<n;i++) kk[i]=kk[i-]+k[i];
for(int i=;i<=n;i++) b[i]=a[i]-k[i-];//feidijian
build(,,n);
scanf("%lld",&m);
while(m--)
{
char s[]; int x,y;
scanf("%s%d%d",s,&x,&y);
if(s[]=='s')
{
ll add=kk[y-]-(x>= ? kk[x-] : );
printf("%lld\n",add+query(,,n,x,y));
}
else
{
ll num=query(,,n,x,x)+y;//can't write b[x] instead of query(1,1,n,x,x)
//int pos=lower_bound(b,b+n+1,num)-b;
//can't use array b!
int l=x,r=n,mid,pos=x;
while(l<=r)
{
mid=(l+r)>>;
if(num>query(,,n,mid,mid))
{
pos=mid;
l=mid+;
}
else r=mid-;
}
update(,,n,x,pos,num);
}
}
return ;
}
codeforces 1136E-Nastya Hasn't Written a Legend的更多相关文章
- codeforces#1136E. Nastya Hasn't Written a Legend(二分+线段树)
题目链接: http://codeforces.com/contest/1136/problem/E 题意: 初始有a数组和k数组 有两种操作,一,求l到r的区间和,二,$a_i\pm x$ 并且会有 ...
- Codeforces 1136E - Nastya Hasn't Written a Legend - [线段树+二分]
题目链接:https://codeforces.com/problemset/problem/1136/E 题意: 给出一个 $a[1 \sim n]$,以及一个 $k[1 \sim (n-1)]$, ...
- Codeforces 1136E Nastya Hasn't Written a Legend 线段树
vp的时候没码出来.. 我们用set去维护, 每一块区域, 每块区域内的元素与下一个元素的差值刚好为ki,每次加值的时候我们暴力合并, 可以发现我们最多合并O(n)次. 然后写个线段树就没了. #in ...
- Codeforces 1136E Nastya Hasn't Written a Legend (线段树教做人系列)
题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后, ...
- Codeforces Round #546 (Div. 2) E - Nastya Hasn't Written a Legend
这题是一个贼搞人的线段树 线段树维护的是 区间和a[i - j] 首先对于update的位置可以二分查找 其次update时候的lazy比较技巧 比如更新的是 l-r段,增加的是c 那么这段的值为: ...
- Nastya Hasn't Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)
题目链接 传送门 题面 题意 给你一个\(a\)数组和一个\(k\)数组,进行\(q\)次操作,操作分为两种: 将\(a_i\)增加\(x\),此时如果\(a_{i+1}<a_i+k_i\),那 ...
- cf1136E. Nastya Hasn't Written a Legend(二分 线段树)
题意 题目链接 Sol yy出了一个暴躁线段树的做法. 因为题目保证了 \(a_i + k_i <= a_{i+1}\) 那么我们每次修改时只需要考虑取max就行了. 显然从一个位置开始能影响到 ...
- 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- ...
- codeforces 1136E 线段树
codeforces 1136E: 题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了, ...
随机推荐
- lunix查询jdk安装路径
在linux系统查找jdk的安装路径:whereis javawhich java (java执行路径)echo $JAVA_HOME echo $PATH在windows查找jdk的安装路径:set ...
- 502Bad Gateway
502 bad gateway,错误的网关的原因 连接超时,我们向服务器发送请求,由于服务器当前链接太多,导致服务器方面无法给予正常的响应,产生此报错,最好去服务器上找原因. 性能测试常见,可能是由于 ...
- FaceNet pre-trained模型以及FaceNet源码使用方法和讲解
Pre-trained models Model name LFW accuracy Training dataset Architecture 20180408-102900 0.9905 CASI ...
- Vultr IP被墙该怎么办
我们创建好Vultr服务器时候,首先需要检测IP地址是否可用,很多IP在国内被墙,导致使用Xshell连接不上,虽然IP能够ping通,但是SSH依然连接不上.那Vultr IP被墙该怎么办呢? 方法 ...
- 网络攻击之代理IP
1.通过代理IP的好处: (1)隐藏自己真实上网地址 (2)突破宽带商访问限制
- JS调用C++
1.注册C++函数. //注册回调函数宏 //根据不同需要支持注册两个函数原型,注意CONNECT_JS_CALL_SIMPLE_HANDLER中注册的函数 //需要提前和HTML调用协调好,参数必须 ...
- 运维人员最常用150个linux命令汇总
命令 功能说明 线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的帮助,比如cd命令. 文件和目录操作命令(18个) l ...
- OpenLayers的view与layer:控制显示内容
view与layer都可以进行显示内容的控制.这两者负责的功能是由区别的. view即显示的地图容器,有以下几个属性: center:[经度,纬度] ,对应的设置函数为view.setCenter() ...
- 一次性安装python常用模块
链接:https://pan.baidu.com/s/1fuIxRUnkJJfzgrbQ8kIgvw 提取码:d1r6 电脑必须是win64才可以安装 Anaconda3安装完成后,不需要自己添加环境 ...
- Maven使用初步
一.安装: 1.下载:http://maven.apache.org/download.cgi 2.设置环境变量 1.创建"M2_HOME",值为Maven安装路径(如:D:\Ja ...