E. Nastya Hasn’t Written a Legend
题意:
输入
n
(
1
e
5
)
n(1e5)
n(1e5);
第二行输入
a
1
,
a
2
,
…
,
a
n
(
−
1
e
9
−
1
e
9
)
a_1,a_2,\dots,a_n(-1e9-1e9)
a1,a2,…,an(−1e9−1e9)
第三行输入
k
1
,
k
2
,
…
,
k
n
−
1
(
−
1
e
9
−
1
e
9
)
k_1,k_2,\dots,k_{n-1}(-1e9-1e9)
k1,k2,…,kn−1(−1e9−1e9)
输入保证
a
i
+
k
i
≤
a
i
+
1
(
1
≤
i
≤
n
−
1
)
a_i+k_i\leq a_{i+1}(1\leq i\leq n-1)
ai+ki≤ai+1(1≤i≤n−1)
输入
q
(
1
e
5
)
q(1e5)
q(1e5)接下来
q
q
q行:
+
,
i
,
x
+,i ,x
+,i,x表示操作
a
i
+
=
x
a_i+=x
ai+=x,在操作过程中若有
a
j
+
k
j
>
a
[
j
+
1
]
(
1
≤
j
≤
n
−
1
)
a_j+k_j>a[j+1](1\leq j\leq n-1)
aj+kj>a[j+1](1≤j≤n−1),那么
a
j
+
1
=
a
j
+
k
j
a_{j+1}=a_j+k_j
aj+1=aj+kj;
s
,
l
,
r
s,l,r
s,l,r表示询问
a
l
+
a
l
+
1
+
⋯
+
a
r
a_l+a_{l+1}+\dots+a_r
al+al+1+⋯+ar。
题解:
首先分析这个序列具有单调的性质;不妨设:
a
1
=
a
1
+
x
1
,
a
2
=
a
1
+
k
1
+
x
2
,
a
3
=
a
1
+
k
1
+
k
2
+
x
3
,
…
,
a
n
=
a
1
+
k
1
+
k
2
+
⋯
+
k
n
−
1
+
x
n
(
0
=
x
1
≤
x
2
≤
x
3
≤
⋯
≤
x
n
)
a_1=a_1+x_1,a_2=a_1+k_1+x_2,a_3=a_1+k_1+k_2+x_3,\dots,a_n=a_1+k_1+k_2+\dots+k_{n-1}+x_n(0=x_1\leq x_2\leq x_3\leq\dots\leq x_n)
a1=a1+x1,a2=a1+k1+x2,a3=a1+k1+k2+x3,…,an=a1+k1+k2+⋯+kn−1+xn(0=x1≤x2≤x3≤⋯≤xn)
只要保证
(
x
1
≤
x
2
≤
x
3
≤
⋯
≤
x
n
)
(x_1\leq x_2\leq x_3\leq\dots\leq x_n)
(x1≤x2≤x3≤⋯≤xn)即可;当
x
i
>
x
i
+
1
x_i>x_{i+1}
xi>xi+1时,使
x
i
+
1
=
x
i
x_{i+1}=x_{i}
xi+1=xi即可。因此用线段树维护
X
X
X数组就好。
当
a
i
+
=
x
a_i+=x
ai+=x时,即
x
i
+
=
x
x_i+=x
xi+=x,二分找到最右边的
j
j
j,使
x
j
≤
x
i
x_j\leq x_i
xj≤xi,并将
x
i
,
x
i
+
1
,
…
,
x
j
x_i,x_{i+1},\dots,x_j
xi,xi+1,…,xj全赋为
x
i
x_i
xi,即可。
最后就查询区间和,就不用说了吧。
代码:
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
//#define int long long
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
#define ll long long
ll n,a[N],sum[N],ssum[N];
ll he[N<<2],tag[N<<2];
void push_down(int p,int l,int r){
if(tag[p]){
int mid=(l+r)>>1;
tag[ls(p)]=tag[rs(p)]=tag[p];
he[ls(p)]=(mid-l+1)*tag[p],he[rs(p)]=(r-mid)*tag[p];
tag[p]=0;
}
}
void push_up(int p){he[p]=he[ls(p)]+he[rs(p)];}
void update(int p,int l,int r,int ql,int qr,ll qz){
if(ql<=l&&r<=qr){
tag[p]=qz;
he[p]=1ll*(r-l+1)*qz;
return;
}
push_down(p,l,r);
int mid=(l+r)>>1;
if(ql<=mid)update(ls(p),l,mid,ql,qr,qz);
if(qr>mid)update(rs(p),mid+1,r,ql,qr,qz);
push_up(p);
}
ll query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return he[p];
push_down(p,l,r);
int mid=(l+r)>>1;ll ans=0;
if(ql<=mid)ans+=query(ls(p),l,mid,ql,qr);
if(qr>mid)ans+=query(rs(p),mid+1,r,ql,qr);
return ans;
}
signed main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++){int t;cin>>t;sum[i]=sum[i-1]+t;}
for(int i=1;i<=n;i++)ssum[i]=ssum[i-1]+a[1]+sum[i-1];
for(int i=1;i<=n;i++)update(1,1,n,i,i,a[i]-a[1]-sum[i-1]);//cout<<a[i]-a[1]-sum[i-1]<<" ";cout<<endl;
int q;
cin>>q;
char c;int l,r;
while(q--){
cin>>c>>l>>r;
if(c=='+'){
ll now=query(1,1,n,l,l);
// cout<<now<<endl;
now+=r;
// cout<<l<<" "<<r<<" "<<now<<endl;
int L=l,R=n,mid,ans;
while(L<=R){
mid=(L+R)>>1;
if(query(1,1,n,mid,mid)<=now)ans=mid,L=mid+1;
else R=mid-1;
}
//cout<<ans<<endl;
update(1,1,n,l,ans,now);
}else{
// cout<<"wen\n";
// cout<<l<<" "<<r<<" "<<query(1,1,n,l,r)<<" "<<ssum[r]-ssum[l-1]<<endl;
cout<<query(1,1,n,l,r)+ssum[r]-ssum[l-1]<<endl;
}
}
return 0;
}