分块WA4个点 马蜂孬求调玄关
查看原帖
分块WA4个点 马蜂孬求调玄关
777809
IOI_AK_TLR楼主2024/10/20 18:39
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n,q,w,l,r,d,a[N],b[N];
int fk[N],dat[N],alladd[N],sum[N],len;
void fkinit(){
	len=sqrt(n);
	for(int i=1;i<=n;i++){
		dat[i]=a[i];
		fk[i]=(i-1)/len+1;
		sum[fk[i]]+=dat[i];
	}
}
void fkadd(int l,int r,int x){
	int s=fk[l],t=fk[r];
	if(s==t)
		for(int i=l;i<=r;i++)
			dat[i]+=x,sum[s]+=x;
	else{
		for(int i=l;fk[i]==s;i++)
			dat[i]+=x,sum[s]+=x;
		for(int i=s+1;i<t;i++)
			alladd[i]+=x,sum[i]+=len*x;
		for(int i=r;fk[i]==t;i--)
			dat[i]+=x,sum[t]+=x;
	}
}
signed main(){
//	freopen("wxyt4.in","r",stdin);
//	freopen("114514.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin>>n>>q>>w;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	fkinit();
	int x=0,tmp_i=1,tmp_j=1,tmp_k=1;
	while(x<w){
		if(tmp_j==n+1){
			tmp_j=1;
			tmp_i<<=1;
			b[tmp_k++]=x;
		}
		x+=a[tmp_j]*tmp_i;
		tmp_j++;
	}
	if(tmp_j!=n+1)
		while(tmp_j<n+1){
			x+=a[tmp_j]*tmp_i;
			tmp_j++;
		}
	b[tmp_k++]=x;
//	
//	for(int i=1;i<tmp_k;i++)
//		cerr<<b[i]<<' ';
	
	while(q--){
		cin>>l>>r>>d;
//		cerr<<"---1---";
		fkadd(l,r,d);
		int tmp_l=(r-l+1)*d;
		int tmp_m=0;
		for(int i=1;i<tmp_k;i++){
			tmp_m+=tmp_l;
			b[i]+=tmp_m;
			tmp_l<<=1;
			if(b[i]>=w)
				tmp_k=i+1;
		}
//		cerr<<"---2---";
		int tmp_n=w-b[tmp_k-2],tmp_o=0,tmp_p;
//		for(int i=1;i<=tmp_k-2;i++){
//			tmp_o+=1ll<<(i-1);
//		}
		tmp_o=1<<(tmp_k-2);
		if(tmp_n%tmp_o==0)
			tmp_p=tmp_n/tmp_o;
		else
			tmp_p=tmp_n/tmp_o+1;
		//tmp_p即为映射到1~n时要查找排名的数
		//分块维护的就是1~n的东西,查找tmp_p时先从大块开始找,
		//找到第一个分块区间和的前缀和大于等于tmp_p的位置
		//对此块详细查找从头开始加直到和大于等于tmp_p
		//此时这个位置就是tmp_n映射到1~n时的结果
		//最终答案是这个结果加上(tmp_k-2)*n
		int tmp_sum=0;
		int i;
		int tmp_ans=0;
		for(i=1;tmp_sum<tmp_p;i++){
			tmp_sum+=sum[i];
		}
//		cerr<<"---3---";
//		cerr<<"---"<<tmp_n<<" "<<tmp_sum<<" "<<tmp_p<<" "<<tmp_o<<" "<<i<<"---";
//		cerr<<'\n';
//		for(int i=1;i<=n;i++){
//			cerr<<fk[i]<<" "<<dat[i]<<" "<<alladd[fk[i]]<<" "<<sum[fk[i]]<<'\n';
//		}  //这部分没问题
		tmp_sum-=sum[i-1];
//		cerr<<"---"<<tmp_sum<<'\n';
		for(int j=(i-2)*len+1;j<=min((i-1)*len,n);j++){
			++tmp_ans;
			tmp_sum+=dat[j]+alladd[fk[j]];
			if(tmp_sum>=tmp_p){
				break;
			}
		}
//		cerr<<"---4---";
//		cerr<<"----"<<tmp_k<<","<<tmp_ans<<","<<i<<'\n';
		cout<<(tmp_k-2)*n+tmp_ans+(i-2)*len-1<<'\n';
	}
	return 0;
}
/*
9 1 4 5 1 4
               |                 |
9 10 14 19 20 24 42 44 52 62 64 72 108
1 1 1 1 1 1 3 3 3 3 3 3
1 1 4 7 10 10 12 12 18 24 30 30

考虑分块解决
*/
2024/10/20 18:39
加载中...