This way
给你一个长度为n的数组,q次操作,每次操作给你
x v 将位置x的值改成v
并且在每一次操作之后你要输出一个位置x(1<=x<=n||x=-1)使得a[x]= ∑ i = 0 x − 1 a [ i ] \sum_{i=0}^{x-1}a[i] ∑i=0x−1a[i]。如果不存在输出-1.
首先考虑是数据结构,那么我们怎么维护某个值和它前缀和的关系?想了一会发现不知道怎么维护,那么改变策略。此时我发现,有可能的位置的序列一定是一个a值单调递增上升的序列。那么根据斐波那契数列的性质,我们最多应该不会超过50次,就会超过int的范围。所以只要每次找到第一个大于等于pre[i](pre表示前缀和)的位置p,然后查看a[p]是否等于pre[p-1],这样子找下去就行了。然后用两个线段树维护前缀和,最大值的位置
#include
using namespace std;
#define ll long long
#define pa pair
const int N=2e5+5;
pa mx[N*4];
ll a[N],pre[N*4],f[N*4];
void build(int l,int r,int root){
if(l==r){
mx[root]={l,a[l]};
return ;
}
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
mx[root]=mx[root<<1];
if(mx[root<<1|1].second>mx[root].second)
mx[root]=mx[root<<1|1];
}
void up_mx(int l,int r,int root,int p,ll v){
if(l==r){
mx[root]={l,v};
return ;
}
int mid=l+r>>1;
if(mid>=p)
up_mx(l,mid,root<<1,p,v);
else
up_mx(mid+1,r,root<<1|1,p,v);
mx[root]=mx[root<<1];
if(mx[root<<1|1].second>mx[root].second)
mx[root]=mx[root<<1|1];
}
void push_down(int root){
if(!f[root])return ;
pre[root<<1]+=f[root];
pre[root<<1|1]+=f[root];
f[root<<1]+=f[root];
f[root<<1|1]+=f[root];
f[root]=0;
}
void up_pre(int l,int r,int root,int ql,int qr,ll v){
if(l>=ql&&r<=qr){
pre[root]+=v;
f[root]+=v;
return ;
}
int mid=l+r>>1;
push_down(root);
if(mid>=ql)
up_pre(l,mid,root<<1,ql,qr,v);
if(mid<qr)
up_pre(mid+1,r,root<<1|1,ql,qr,v);
pre[root]=pre[root<<1]+pre[root<<1|1];
}
ll q_pre(int l,int r,int root,int p){
if(l==r)
return pre[root];
ll ans=0;
int mid=l+r>>1;
push_down(root);
if(mid>=p)ans=q_pre(l,mid,root<<1,p);
else ans=q_pre(mid+1,r,root<<1|1,p);
return ans;
}
int q_mx(int l,int r,int root,int ql,int qr,ll v){
if(mx[root].second<v)return -1;
if(l==r)return mx[root].first;
int mid=l+r>>1;
if(l>=ql&&r<=qr){
if(mx[root<<1].second>=v)return q_mx(l,mid,root<<1,ql,qr,v);
else return q_mx(mid+1,r,root<<1|1,ql,qr,v);
}
int ans=-1;
if(mid>=ql&&mx[root<<1].second>=v)
ans=q_mx(l,mid,root<<1,ql,qr,v);
if(ans!=-1)return ans;
if(mid<qr)
ans=q_mx(mid+1,r,root<<1|1,ql,qr,v);
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
up_pre(1,n,1,i,n,a[i]);
}
build(1,n,1);
while(m--){
int p;
ll v;
scanf("%d%lld",&p,&v);
up_mx(1,n,1,p,v);
up_pre(1,n,1,p,n,v-a[p]);
a[p]=v;
if(a[1]==0){
printf("1\n");
continue;
}
int sta=1,f=-1;
for(int i=50;i&&sta<n;i--){
v=q_pre(1,n,1,sta);
int pos=q_mx(1,n,1,sta+1,n,v);
v=q_pre(1,n,1,pos-1);
if(pos==-1)break;
if(a[pos]==v){
f=pos;
break;
}
else sta=pos;
}
printf("%d\n",f);
}
return 0;
}