CF1707E Replace
Neutralized · · 个人记录
*3500。把我吓到了,其实这题比较水,已经快做出来了。
顺便一提 CF 怎么这么喜欢出 ST 表。
二元组不好看,换成
首先对于同一个
然后观察可以发现这个
也就是随便戳若干断点,分割出的区间的函数并就是整个区间的函数。
其实这是一个更强的结论:若干区间并的函数值等于这些区间函数值的并。
(这里有个条件的,就是这些区间相邻的两个
考虑这个有什么用,可以写 ST 表做到
妈的,差一点就想出来了 /fn /fn /fn
应该给自己留更多思考时间的。现在浑身难受。
现在我们抓着 ST 表继续搞。那么我们使用以上结论,设 ST 表划分的区间是
考虑证明
证明:
Upd:关于这里可以再次使用结论有一个条件就是
归纳可知
那么就可以魔改一下 ST 表了,我们在前面再加一维
启发性大概在于这种不好搞的函数尝试分拆、组合来观察可并性,或者找单调性,然后利用这些性质套上数据结构维护;还有就是做若干次给定变换可以考虑倍增。
Upd:Happy New Year 了。
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define Tp template<class T>
namespace SlowIO{
const int End=1e6; static char outp[End],buf[End],*p1=buf,*p2=buf; inline char gchar(){ return p1==p2&&(p2=(p1=buf)+fread(buf,1,End,stdin),p1==p2)?EOF:*p1++; }
Tp inline void rd(T &x,char i=gchar(),bool f=0){ x=0; while(i<48||i>57) f|=i=='-',i=gchar(); while(i>=48&&i<=57) x=(x<<3)+(x<<1)+(i^48),i=gchar(); f&&(x=-x); } Tp inline void op(T x,int out=0){ if(!x){ putchar(48); return; } x<0&&(x=-x,putchar('-')); while(x) outp[++out]=(x%10)^48,x/=10; while(out) putchar(outp[out--]); } Tp inline void writeln(T x){ op(x),putchar('\n'); } Tp inline void writesp(T x){ op(x),putchar(' '); } Tp inline void write(T x,char c=0){ op(x); c&&putchar(c); }
}; using namespace SlowIO;
const int N = 100003;
int n,q,a[N],Log2[N];
struct Data{ int l,r; inline Data operator +(const Data &a){ return {min(l,a.l),max(r,a.r)}; } }st[18][18][N];
auto Chk = [](Data x){ return x.l==1&&x.r==n; };
auto Qry = [](int i,int l,int r){ int k = Log2[r-l+1]; return st[i][k][l]+st[i][k][r-(1<<k)+1]; };
main(){
rd(n),rd(q); bool f1=0,f2=0;
for(int i=1;i<=n;++i) rd(a[i]),st[0][0][i]={a[i],a[i]},f1|=a[i]==1,f2|=a[i]==n;
for(int i=2;i<=n;++i) Log2[i]=Log2[i>>1]+1;
for(int i=n;i>=1;--i)
for(int j=1;i+(1<<j)-1<=n;++j)
st[0][j][i]=st[0][j-1][i]+st[0][j-1][i+(1<<j-1)];
for(int k=1;k<18;++k)
for(int i=n;i>=1;--i)
for(int j=1;i+(1<<j)-1<=n;++j)
st[k][j][i]=Qry(k-1,st[k-1][j][i].l,st[k-1][j][i].r);
int l,r; while(q--){
rd(l),rd(r); int res=0; Data now = {l,r};
if(Chk(now)){ puts("0"); continue; }
if(!f1||!f2){ puts("-1"); continue; }
for(int i=17;i>=0;--i){
Data t = Qry(i,now.l,now.r); if(!Chk(t)) now=t,res|=1<<i;
} ++res,now=Qry(0,now.l,now.r),writeln(Chk(now)?res:-1);
}
}