版权声明:欢迎dalao指出错误暴踩本SD,蒟蒻写的博客转载也要吱一声 https://blog.csdn.net/enjoy_pascal/article/details/82715379
description
analysis
正解鬼畜线段树
设修改的位置为 ,那么 前面的答案不变,考虑 区间即可
我们在线段树上二分,找到第一个位置 使 ,这样 才有可能是答案
然后判断 ,若不满足则继续在 区间里找
注意在第一个二分出的 之后的所有 ,要判断的是
时间复杂度
反正能过
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 200005
#define ll long long
#define fo(i,a,b) for (register int i=a;i<=b;i++)
#define fd(i,a,b) for (register int i=a;i>=b;i--)
using namespace std;
ll sum[MAXN*4],mx[MAXN*4];
ll a[MAXN];
ll n,m;
__attribute__((optimize("-O3")))
ll read()
{
ll x=0,f=1;
char ch=getchar();
while (ch<'0' || '9'<ch)
{
if (ch=='-')f=-1;
ch=getchar();
}
while ('0'<=ch && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
__attribute__((optimize("-O3")))
void maketree(ll t,ll l,ll r)
{
if (l==r)
{
sum[t]=mx[t]=a[l];
return;
}
ll mid=(l+r)/2;
maketree(t*2,l,mid),maketree(t*2+1,mid+1,r);
sum[t]=sum[t*2]+sum[t*2+1];
mx[t]=max(mx[t*2],mx[t*2+1]);
}
__attribute__((optimize("-O3")))
ll query_sum(ll t,ll l,ll r,ll x,ll y)
{
if (l==x && y==r)return sum[t];
ll mid=(l+r)/2;
if (y<=mid)return query_sum(t*2,l,mid,x,y);
else if (x>mid)return query_sum(t*2+1,mid+1,r,x,y);
else return query_sum(t*2,l,mid,x,mid)+query_sum(t*2+1,mid+1,r,mid+1,y);
}
__attribute__((optimize("-O3")))
void change(ll t,ll l,ll r,ll x)
{
if (l==r)
{
sum[t]=mx[t]=a[x];
return;
}
ll mid=(l+r)/2;
if (x<=mid)change(t*2,l,mid,x);
else change(t*2+1,mid+1,r,x);
sum[t]=sum[t*2]+sum[t*2+1];
mx[t]=max(mx[t*2],mx[t*2+1]);
}
__attribute__((optimize("-O3")))
ll find(ll t,ll l,ll r,ll x,ll y)
{
if (l==x && r==y)return mx[t];
ll mid=(l+r)/2;
if (y<=mid)find(t*2,l,mid,x,y);
else if (x>mid)find(t*2+1,mid+1,r,x,y);
else return max(find(t*2,l,mid,x,mid),find(t*2+1,mid+1,r,mid+1,y));
}
__attribute__((optimize("-O3")))
int main()
{
//freopen("readin.txt","r",stdin);
freopen("challenge.in","r",stdin);
freopen("challenge.out","w",stdout);
n=read(),m=read();
fo(i,1,n)a[i]=read();
maketree(1,1,n);
ll t=1,s=0;
while (a[t]!=s)
{
if (t==n)
{
t=-1;
break;
}
ll l=t+1,r=n;
if (find(1,1,n,l,r)>=s)
{
while (l<r)
{
ll mid=(l+r)/2;
find(1,1,n,1,mid)>=s?r=mid:l=mid+1;
}
t=r;
}
else
{
t=-1;
break;
}
s=query_sum(1,1,n,1,t-1);
}
fo(i,1,m)
{
ll x=read(),y=read();
a[x]=y;
change(1,1,n,x);
if (t!=-1 && t<x)
{
printf("%lld\n",t);
continue;
}
t=x,s=t>1?query_sum(1,1,n,1,t-1):s=0;
while (a[t]!=s)
{
if (t==n)
{
t=-1;
break;
}
ll l=t+1,r=n;
if (find(1,1,n,l,r)>=s)
{
while (l<r)
{
ll mid=(l+r)/2;
find(1,1,n,1,mid)>=s?r=mid:l=mid+1;
}
t=r;
}
else
{
t=-1;
break;
}
s=query_sum(1,1,n,1,t-1);
}
printf("%lld\n",t);
}
return 0;
}