题目链接:https://codeforces.com/problemset/problem/1136/E

题意:

给出一个 $a[1 \sim n]$,以及一个 $k[1 \sim (n-1)]$,初始保证所有的 $1 \le i \le n-1$ 都满足 $a[i]+k[i] \le a[i+1]$。

现在有两种操作:

  第一种是令指定的 $a[i]$ 加上一个非负整数 $x$,此时若有 $a[i] + k[i] > a[i+1]$,则 $a[i+1]$ 变为 $a[i] + k[i]$,往后依次类推。

  第二种是给定一个区间 $[l,r]$ 求 $a[l] + \cdots + a[r]$。

题解:

首先,我们知道对一个 $a[i]$ 加上 $x$ 后,根据其后面的 $a[i] + k[i] \le a[i+1], a[i+1] + k[i+1] \le a[i+2], \cdots$ 的“松紧程度”的变化,$a[i]$ 加上 $x$ 其带来的影响会逐步减弱,直到在某个位置 $j$ 之后完全消失,这个 $a[j]$ 是最后一个要被修改的数。

那么,如果我们找到了这个区间 $[i,j]$,我们现在要做的修改操作,就是要对这个区间进行一定的修改。

不难发现,这个区间内的第一个数变成了 $a[i]+x$,第二个变成了 $a[i]+x+k[i]$,第三个变成了 $a[i]+x+k[i]+k[i+1]$,依次类推……

考虑这个式子可以分为两部分:$a[i] + x$ 部分,以及 $k[i] + k[i+1] + \cdots$ 部分。

可以考虑分开维护这两个部分,前一部分很好维护,线段树区间更新;后一部分直接维护比较困难,我们可以这样维护:

$k[i],k[i]+k[i+1],k[i]+k[i+1]+k[i+2],\cdots$,不难看出是一个类似于 $k$ 数组的前缀和的求和,举个栗子:

$k_3 ,\: k_3+k_4 ,\: k_3+k_4+k_5 ,\: k_3+k_4+k_5+k_6$,如果是前缀和求和,那么应当是 $k_1+k_2+k_3 \:,\: k_1+k_2+k_3+k_4 \:,\: k_1+k_2+k_3+k_4+k_5 \:,\: k_1+k_2+k_3+k_4+k_5+k_6$。

也就是说,要在前缀和上减掉 $4 \times (k_1+k_2)$,不难发现,这个值是比较好维护的,是对某一段区间直接赋值,所以可以用线段树维护这个东西。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e18;
const int maxn=1e5+;
int n,q;
ll a[maxn],k[maxn],s[maxn]; struct Node
{
int l,r;
ll val,lazy;
void update(ll x)
{
val=(r-l+)*x;
lazy=x;
}
};
struct SegmentTree
{
#define ls (rt<<1)
#define rs (rt<<1|1)
Node o[maxn<<];
void pushdown(int rt)
{
if(o[rt].lazy!=-INF)
{
o[ls].update(o[rt].lazy);
o[rs].update(o[rt].lazy);
o[rt].lazy=-INF;
}
}
void pushup(int rt)
{
o[rt].val=o[ls].val+o[rs].val;
}
void build(int rt,int l,int r,ll v[])
{
o[rt].l=l, o[rt].r=r;
o[rt].lazy=-INF;
if(l==r)
{
o[rt].val=v[l];
return;
}
int mid=(l+r)>>;
build(ls,l,mid,v);
build(rs,mid+,r,v);
pushup(rt);
}
void update(int rt,int st,int ed,ll val)
{
if(st<=o[rt].l && o[rt].r<=ed)
{
o[rt].update(val);
return;
}
pushdown(rt);
int mid=(o[rt].l+o[rt].r)>>;
if(st<=mid) update(ls,st,ed,val);
if(mid<ed) update(rs,st,ed,val);
pushup(rt);
}
ll query(int rt,int st,int ed)
{
if(st<=o[rt].l && o[rt].r<=ed) return o[rt].val;
pushdown(rt);
ll res=;
int mid=(o[rt].l+o[rt].r)>>;
if(st<=mid) res+=query(ls,st,ed);
if(mid<ed) res+=query(rs,st,ed);
return res;
}
}T[]; inline ll getval(int p)
{
return T[].query(,p,p)+k[p]-T[].query(,p,p);
}
void modify(int p,ll x)
{
int l=p, r=n;
ll base=getval(p);
while(l<r)
{
int mid=(l+r+)>>;
if(base+x+k[mid]-k[p]>getval(mid)) l=mid;
else r=mid-;
}
T[].update(,p,r,base+x);
T[].update(,p,r,k[p]);
} int main()
{
ios::sync_with_stdio();
cin.tie(), cout.tie(); cin>>n;
for(int i=;i<=n;i++) cin>>a[i]; k[]=s[]=;
for(int i=;i<=n;i++) cin>>k[i], k[i]+=k[i-], s[i]=s[i-]+k[i]; T[].build(,,n,a);
T[].build(,,n,k); cin>>q;
char op[];
while(q--)
{
cin>>op;
if(op[]=='+')
{
int p; ll x; cin>>p>>x;
modify(p,x);
}
if(op[]=='s')
{
int l,r; cin>>l>>r;
ll res1=T[].query(,l,r);
ll res2=s[r]-s[l-]-T[].query(,l,r);
cout<<res1+res2<<'\n';
}
}
}

有一个注意点是懒标记初始化成负无穷。

Codeforces 1136E - Nastya Hasn't Written a Legend - [线段树+二分]的更多相关文章

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

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

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

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

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

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

  4. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  5. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  6. [Codeforces 464E] The Classic Problem(可持久化线段树)

    [Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...

  7. Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

    题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l, ...

  8. Codeforces 671C - Ultimate Weirdness of an Array(线段树维护+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 *2800 的 DS,不过还是被我自己想出来了 u1s1 这个 D1C 比某些 D1D 不知道难到什么地方去了 首先碰到这类问题我们肯定考 ...

  9. Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq

    B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/pro ...

随机推荐

  1. 【centos6.6环境搭建】Github unable to access SSL connect error出错处理

    问题 克隆github项目出现SSL connect error git clone https://github.com/creationix/nvm Cloning into 'nvm'... f ...

  2. 单片机成长之路(51基础篇) - 007 CH340CH341最全说明

    比较全的CH340,CH341应用说明 CH340 以前用USB转串口时图方便一般也都是直接买现成的USB转串口模块,但是后面设计需要,不等不将CH340这个模块集成到电路板中,经过多次失败,终于得到 ...

  3. Django Http请求生命周期

    day54 请求响应Http 1.发送Http请求 2.服务器接收,根据请求头中的的url在路由关系表中进行匹配(从上到下) 3.匹配成功后,执行指定的views函数 4.业务处理 URL----&g ...

  4. 100BASE-TX、100Base-FX等含义

    100BASE-TX:双绞线,使用两对非屏蔽双绞线或两对1类屏蔽双绞线连接,传输距离100米 100Base-FX,是在光纤上实现的100 Mbps以太网标准,其中F指示光纤,IEEE标准为802.3 ...

  5. 居于U2000手机管理光猫,小区运营商FTTH光猫注册神器,MA5680T手机管理,自动添加光猫

    此软件居于U2000开发,需要U2000管理支持 主要功能: 光猫查看->上线情况.下线原因.下线时间.光猫重启.光模块发送功能.接收功能.温度 Radius诊断->用户基本信息.拨打电话 ...

  6. 又一次认识java(七) ---- final keyword

    你总以为你会了,事实上你仅仅是一知半解. final 关键字概览 final关键字可用于声明属性.方法.參数和类,分别表示属性不可变.方法不可覆盖.參数不可变和类不能够继承. 我们来分别看看它的使用方 ...

  7. java生成txt文件,读txt文件

    1.方法1 public static void main(String[] args) { try { FileWriter fileWriter = new FileWriter("c: ...

  8. Centos6.8 下 从零开始 部署 Java Web 应用

    一.硬件信息 CPU: [root@localhost ~]# grep 'physical id' /proc/cpuinfo | sort -u | wc -l 2 [root@localhost ...

  9. node-log4js3.0.6配置

    const log4js = require('log4js'); const conf = { "appenders": { "access": { &quo ...

  10. GitLab push除发Jenkins事件

    1.打开Jenkins项目配置 2.勾选Trigger builds remotely (e.g., from scripts) 3.Authentication Token随便填个内容(比方1234 ...