代码如下,用的是线段树,递归建树加求区间值,用二分来找其它树的范围,代码较抽象(弱)
但是会爆内存
#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;
}