20pts,求调
查看原帖
20pts,求调
1252771
Never_Lost楼主2024/10/22 19:50

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;
}
2024/10/22 19:50
加载中...