WA 5~12,T 13~20,我思路是:线段树区改查+大小回合二分,
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*1e5+7;
ll tree[4*N]={0};
ll tag[4*N];
ll d[N];
ll n=0,q,w;
void build(ll s,ll t,ll p){
tree[p]=0;
if(s==t){
tree[p]=d[s];
return;
}
ll mid=(s+t)>>1;
build(s,mid,2*p);
build(mid+1,t,2*p+1);
tree[p]=tree[2*p+1]+tree[2*p];
return;
}
void lt(ll l,ll r,ll k,ll p){
tag[p]+=k;
tree[p]+=(r-l+1)*k;
}
void pushdown(ll l,ll r,ll mid,ll p){
if(!tag[p]){
return;
}
lt(l,mid,tag[p],2*p);
lt(mid+1,r,tag[p],2*p+1);
tag[p]=0;
}
void updata(ll l,ll r,ll s,ll t,ll p,ll k){
if(s>=l&&t<=r){
lt(s,t,k,p);
return;
}
ll mid=s+t>>1;
pushdown(s,t,mid,p);
if(l<=mid){
updata(l,r,s,mid,2*p,k);
}
if(r>mid){
updata(l,r,mid+1,t,2*p+1,k);
}
tree[p]=tree[2*p]+tree[2*p+1];
return;
}
ll query(ll l,ll r,ll s,ll t,ll p){
if(s>=l&&t<=r){
return tree[p];
}
ll ans=0;
ll mid=s+t>>1;
pushdown(s,t,mid,p);
if(l<=mid){
ans+=query(l,r,s,mid,2*p);
}
if(mid<r){
ans+=query(l,r,mid+1,t,2*p+1);
}
return ans;
}
ll sum(ll tp){//快速调用query(当成1~tp前缀和)
return query(1,tp,1,n,1);
}
int main(){
cin>>n>>q>>w;
for(ll i=1;i<=n;i++){
cin>>d[i];
}
build(1,n,1);
for(ll i=1;i<=q;i++){
ll lsl,lsr,d;
cin>>lsl>>lsr>>d;
updata(lsl,lsr,1,n,1,d);
ll l=0,r=31,lsw=w;
ll ans=0;
while(l<r){//二分多少个大回合
ll mid=l+r>>1;
if(sum(n)*((1<<mid)-1)<w){
ans=mid;
l=mid+1;
}else{
r=mid;
}
}
lsw-=sum(n)*((1<<ans)-1);
ll lsans=0;
l=1,r=n;
while(l<r){//二分小回合撑到哪
ll mid=l+r>>1;
if(sum(mid)*(1<<ans)<lsw){
l=mid+1;
lsans=mid;
}else{
r=mid;
}
}
cout<<n*ans+lsans<<endl;
}
return 0;
}