Problem

Hint

Solution
- 首先,我们先求出未操作时的ans。
- 对于一个令Px=yP_x=yPx=y的操作,显然,若ans<x,则ans不变;否则,ans应为区间[x,n]中某一点。
- 设ans当前在位置t,观察一下它会如何变化。
- 记pre=∑i=1tPipre=\sum_{i=1}^t P_ipre=∑i=1tPi,若pre=2Ptpre=2P_tpre=2Pt,则显然t为史上最大毒瘤。直接return。
- 否则,我们在区间[t+1,n]中找到另一个点t’,满足Pt′≥preP_{t'}≥prePt′≥pre且t’尽量小。这个东西直接上线段树二分。
- 我们令t=t’,重复上述操作。
- 分析一波时间复杂度。
- 最坏情况应为每次找到的t’=t+1。令t=1,若P={1,2,4,8,16...}P=\{1,2,4,8,16...\}P={1,2,4,8,16...},则每次t’=t+1,且都是刚好满足Pt′=pre+1P_{t'}=pre+1Pt′=pre+1,于是一直找下去。
- 而上述数列即为共比为2的等比数列。囿于Pi≤109P_i≤10^9Pi≤109,其长度必然≤log2109≤\log_210^9≤log2109。
- 每次修改、查询pre,使用线段树或树状数组,O(log2n)O(\log_2n)O(log2n);找t’用线段树二分,也是O(log2n)O(\log_2n)O(log2n)。因此,时间复杂度为O(n∗log2n+m∗log22n∗log2109)O(n*\log_2n+m*\log^2_2n*\log_210^9)O(n∗log2n+m∗log22n∗log2109)(边读入边插数)or O(n+m∗log22n∗log2109)O(n+m*\log^2_2n*\log_210^9)O(n+m∗log22n∗log2109)(打个O(n)O(n)O(n)的建树)。
Code
#include <bits/stdc++.h>
#define A v<<1
#define B A|1
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int N=2e5+1;
int i,n,m,p[N],ans,x,y;
struct node
{
ll s,mx;
}t[N<<3];
template<class T>inline T max(T &x,T &y) {return x>y?x:y;}
void read(int&x)
{
char ch=getchar(); x=0;
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
}
void modify(int v,int l,int r)
{
if(l==r) {t[v].s=t[v].mx=p[x]; return;}
int m=l+r>>1;
x<=m ? modify(A,l,m) : modify(B,m+1,r);
t[v].s=t[A].s+t[B].s;
t[v].mx=max(t[A].mx,t[B].mx);
}
int px,py;
ll pre;
ll Qsum(int v,int l,int r)
{
if(px> r|l> py) return 0;
if(px<=l&r<=py) return t[v].s;
int m=l+r>>1;
return Qsum(A,l,m)+Qsum(B,m+1,r);
}
ll Qpos(int v,int l,int r)
{
if(px>r |l> py) return 1e9;
int m=l+r>>1;
if(px<=l&r<=py)
{
if(t[v].mx<pre) return 1e9;
if(l==r) return l;
return t[A].mx>=pre ? Qpos(A,l,m) : Qpos(B,m+1,r);
}
return min(Qpos(A,l,m),Qpos(B,m+1,r));
}
int get(int x)
{
while(x<=n)
{
px=1; py=x;
pre=Qsum(1,1,n);
if(pre==2*p[x]) return x;
if(x==n) return -1;
px=x+1; py=n;
x=Qpos(1,1,n);
}
return -1;
}
int main()
{
freopen("challenge.in","r",stdin);
freopen("challenge.out","w",stdout);
read(n); read(m);
fo(x,1,n) read(p[x]), modify(1,1,n);
ans=get(1);
fo(i,1,m)
{
read(x); read(y);
p[x]=y, modify(1,1,n);
if(ans==-1) ans=get(1);
else
if(ans>= x) ans=get(x);
printf("%d\n",ans);
}
}