题解:CF1707E Replace
wing_heart · · 题解
Replace
更好的阅读体验
题意
给你一个长度为
solution
看了feecle大佬的题解后对其中的结论有也许是另一种理解方式。
答案非严格上界是
首先题目的操作与取 显然我没有可以发现:
证明(或者应该叫理解方式):对于每个
蒟蒻的我不能直接观察出推论,但是也许可以这么想:我们考虑对所有
以此类推,可以得到
所以我们不需要求所有的
因为
因此考虑倍增。先求所有
对每个询问,倍增,每次计算 RMQ 判断是否可以得到区间
总时间复杂度是
据说猫树可以单
update 2025.08.27:感谢 @fjy666 的 Hack。错误原因是函数 _cal() 里对长度为
长度为
- 因为
f(i,i) 得到的区间长度也是1 ,无法得到[1,n] 。 - 若求
f(l,r) 时存在l \le i < r ,f(i,i+1) 的长度为1 ,则f(i,i+1) 可以被f(i-1,i),f(i+1,i+2) 覆盖。
综上,我们可以不考虑长度为
由于区间
constexpr pii del = {N,0};
if(x.fi==x.se || x==del) return del;
(Hack 前写的是 if(x.fi==x.se) return x;)
顺带将
仍然不知道怎么单
看了别的题解,使用线段树代替 ST 表做 RMQ 可以做到空间单
code
如果你对 ST 表比较熟悉,代码不算难写。
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
constexpr int N=1e5+7;
#define isdigit(x) (x>='0'&&x<='9')
template <typename T>
void read(T &x) {
x=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) ;
for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
template <typename T>
void write(T x,char ch) {
static int st[20];
int top=0;
do {
st[top++]=x%10;
x/=10;
}while(x);
while(top) putchar(st[--top]+'0');
putchar(ch);
}
int n,q;
int a[N];
int l,r;
typedef pair<int,int> pii;
constexpr pii del = {N,0};
#define fi first
#define se second
pii st[50][25][N];
pii cal(pii a,pii b) { return {min(a.fi,b.fi),max(a.se,b.se)}; }
pii _cal(int p,pii x) {
if(x.fi==x.se || x==del) return del;
int lg=__lg(x.se-x.fi);
return cal(st[p][lg][x.fi],st[p][lg][x.se-(1<<lg)]);
}
#define mp make_pair
int main() {
read(n),read(q);
rep(i,1,n) read(a[i]);
rep(i,1,n-1) st[0][0][i]={min(a[i],a[i+1]),max(a[i],a[i+1])};
int lg=__lg(n);
++lg;
rep(k,1,lg) for(int i=1;i+(1<<k)-1<=n-1;i++) st[0][k][i]=cal(st[0][k-1][i],st[0][k-1][i+(1<<(k-1))]);
rep(p,1,lg<<1) {
rep(i,1,n-1) st[p][0][i]=_cal(p-1,st[p-1][0][i]);
rep(k,1,lg) for(int i=1;i+(1<<k)-1<=n-1;i++) st[p][k][i]=cal(st[p][k-1][i],st[p][k-1][i+(1<<(k-1))]);
}
rep(i,1,q) {
read(l),read(r);
if(l==1&&r==n) {
puts("0");
continue;
}
if(l==r) {
puts("-1");
continue;
}
pii y={l,r};
int cnt=0;
per(p,lg<<1,0) {
pii x=_cal(p,y);
if(x!=mp(1,n)) y=x,cnt+=(1<<p);
}
if(y!=mp(1,n)) y=_cal(0,y),cnt++;
if(y==mp(1,n)) write(cnt,'\n');
else puts("-1");
}
}