爆内存了
查看原帖
爆内存了
1041612
yj5748361楼主2024/2/27 15:32

代码如下,用的是线段树,递归建树加求区间值,用二分来找其它树的范围,代码较抽象(弱) 但是会爆内存

#include <stdio.h>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
const int M=2e6;
int n,m,a[M+5],temp1,val,dat;
ll d[M+5];
void build(int s,int t,int p){
	if(s==t){
		d[p]=a[s];
		return;
	}
	ll m=s+((t-s)>>1);
	build(s,m,p*2),build(m+1,t,p*2+1);
	d[p]=d[p*2]+d[p*2+1];
}
ll getsum(int l,int r,int s,int t,int p){
	if(l<=s&&t<=r) return d[p];
	int m=s+((t-s)>>1);
	ll sum=0;
	if(l<=m)sum+=getsum(l,r,s,m,p*2);
	if(r>m)sum+=getsum(l,r,m+1,t,p*2+1);
	return sum;
}
void cx(ll tot){
	int wz;
	build(1,n,1);
	if(d[1]<tot) {
		printf("none\n");
		return;
	}
	else{
		int l=1,r=1;
		while(getsum(1,r,1,n,1)<tot&&r<n) l=r,r=min(r*2,n);
		while(l<r){
			int m=(l+r)/2;
			if(getsum(1,m,1,n,1)>=tot) r=m;
			else l=m+1;
		}
		wz=r;
	}
	if(getsum(1,wz,1,n,1)==tot){
		printf("1 %d\n",wz);
		return;
	}
	if(getsum(1,wz,1,n,1)+a[wz+1]==tot){
		printf("1 %d\n",wz+1);
		return;
	}
	int len1=1,len2=wz,l;
	while(getsum(1,len1,1,n,1)==2*len1) l=len1,len1*=2;
	while(l<len1){
		int m=(l+len1)/2;
		if(getsum(l,m,1,n,1)==2*(m-l+1)) len1=m;
		else l=m+1;
	}
	while(getsum(wz,len2,1,n,1)==2*(len2-wz+1)) l=len2,len2*=2;
	while(l<len2){
		int m=(l+len2)/2;
		if(getsum(l,len2,1,n,1)==2*(m-l+1)) len2=m;
		else l=m+1;
	}
	if(len1<len2-wz+1) printf("%d %d\n",2+len1,wz+len1);
	else printf("%d %d\n",2+len2-wz,len2+1);
}
int main(){
	scanf("%lld %lld",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld",a+i);
	for(int i=0;i<m;i++){
		char temp;
		scanf("%c",&temp);
		if(temp=='\n') scanf("%c",&temp);
		if(temp=='A') {
			scanf("%lld",&temp1);
			cx(temp1);
		}
		else{
			scanf("%lld %lld",&dat,&val);
			a[dat]=val;
		}
	}
	return 0;
}
2024/2/27 15:32
加载中...