传送门: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的更多相关文章

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

    题目链接: http://codeforces.com/contest/1136/problem/E 题意: 初始有a数组和k数组 有两种操作,一,求l到r的区间和,二,$a_i\pm x$ 并且会有 ...

  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. Codeforces Round #546 (Div. 2) E - Nastya Hasn't Written a Legend

    这题是一个贼搞人的线段树 线段树维护的是 区间和a[i - j] 首先对于update的位置可以二分查找 其次update时候的lazy比较技巧 比如更新的是 l-r段,增加的是c 那么这段的值为: ...

  6. 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\),那 ...

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

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

  8. 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- ...

  9. codeforces 1136E 线段树

    codeforces 1136E: 题意:给你一个长度为n的序列a和长度为n-1的序列k,序列a在任何时候都满足如下性质,a[i+1]>=ai+ki,如果更新后a[i+1]<ai+ki了, ...

随机推荐

  1. WriteFile

    从R3 ,到磁盘 1:kernel32  WriteFile 1) 挺惊讶的,符号好使了, 前面大概4条判断,根据句柄判断要写到什么地方,一共有4个地方可能要去, stdin   stdout   s ...

  2. flink流的执行大致流程图

  3. GNU 交叉工具链的介绍与使用

    常用工具介绍 名称 归属 作用 arm­linux­as binutils 编译 ARM 汇编程序 arm­linux­ar binutils 把多个.o 合并成一个.o 或静态库(.a) arm­l ...

  4. delphi 用户可以点击格式修改进行模板修改

    过程 TlistRepAdd.Btn_GCListRepEditClick窗口 TlistRepAdd 补打流程单 1. 给用户权限 呈现出格式修改按钮 procedure TlistRepAdd.B ...

  5. K-Anonymous Sequence

    K-Anonymous Sequence 给出一个递增的长度为n的序列\(\{a_i\}\),现在你可以进行一次操作,选择若干个数,分别减少任意一个正整数,定义权值为这些正整数之和,询问操作使得新序列 ...

  6. Orika JavaBean映射工具探秘

    Orika是一个简单.快速的JavaBean拷贝框架,Orika使用字节代码生成来创建具有最小开销的快速映射器. 关于: 作为开发人员,我们必须为业务问题提供解决方案,我们希望利用我们的时间来做真正重 ...

  7. com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

    报错: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected estab ...

  8. HDU-1852-Beijing 2008-一个神奇的公式求逆元

    As we all know, the next Olympic Games will be held in Beijing in 2008. So the year 2008 seems a lit ...

  9. 第九篇:Spring的applicationContext.xml配置总结

    在前面的一篇日志中,记录了web.xml配置启动的顺序,web启动到监听器ContextLoaderListener时,开始加载spring的配置文件applicationContext.xml(通常 ...

  10. git撤销修改及版本回退

    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file. 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步, ...