首先有一个结论:一定存在一种最优方案,先在起点等若干时间,然后一口气走一圈完成任务。(任何一种最优方案我们从经过的最后一个点往回倒一圈就一定满足)
于是我们把环拆成连,就是求
Minni=1{Maxn+i−1j=i{Tj−(j−i)}+n−1}
M
i
n
i
=
1
n
{
M
a
x
j
=
i
n
+
i
−
1
{
T
j
−
(
j
−
i
)
}
+
n
−
1
}
也就是求
Minni=1{Max2nj=i{Tj−j}+i}+n−1
M
i
n
i
=
1
n
{
M
a
x
j
=
i
2
n
{
T
j
−
j
}
+
i
}
+
n
−
1
考虑线段树维护这个东西。
对于节点p,维护区间[L,R],记mx表示
MaxRi=L{Ti−i}
M
a
x
i
=
L
R
{
T
i
−
i
}
,
f
f
表示
那么
tr[1].f
t
r
[
1
]
.
f
就是我们要的答案。
f
f
可以用一个query来查询,查询时右子树信息对左子树信息有影响。
于是复杂度就是
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,ty,lastans,a[N<<1];
struct node{
int mx,f;
}tr[N<<3];
inline int query(int p,int l,int r,int val){
if(l==r) return max(tr[p].mx,val)+l;int mid=l+r>>1;
if(tr[p<<1|1].mx<=val) return min(mid+1+val,query(p<<1,l,mid,val));
return min(tr[p].f,query(p<<1|1,mid+1,r,val));
}
inline void pushup(int p,int l,int mid){
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
tr[p].f=query(p<<1,l,mid,tr[p<<1|1].mx);
}
inline void build(int p,int l,int r){
if(l==r){tr[p].mx=a[l];tr[p].f=tr[p].mx+l;return;}
int mid=l+r>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);pushup(p,l,mid);
}
inline void change(int p,int l,int r,int x,int y){
if(l==r){tr[p].mx=y;tr[p].f=tr[p].mx+l;return;}
int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,y);
else change(p<<1|1,mid+1,r,x,y);
pushup(p,l,mid);
}
int main(){
// freopen("a.in","r",stdin);
n=read();m=read();ty=read();
for(int i=1;i<=n;++i) a[n+i]=a[i]=read(),a[i]-=i,a[n+i]-=n+i;
build(1,1,n<<1);printf("%d\n",lastans=tr[1].f+n-1);
while(m--){
int x=read(),y=read();if(ty) x^=lastans,y^=lastans;
change(1,1,n<<1,x,y-x);change(1,1,n<<1,x+n,y-n-x);
printf("%d\n",lastans=tr[1].f+n-1);
}return 0;
}