*题解:P14255 列车(train)
解析
注意到对于一个起点站 \(x\),必定有另一个站 \(y > x\) 使得所有以 \(x\) 为起点站,终点站编号小于 \(y\) 的路线均处于停开状态,而所有终点站编号大于等于 \(y\) 的路线均不处于停开状态。
故考虑对于每个站 \(i\),维护 \(a_i\) 表示以 \(i\) 为起点站的非停开线路的最小终点站编号。这样,我们就得到了一个查询和修改均为 \(O(nm)\) 的做法。
考虑优化。对于一次修改操作 \((l,r)\),实际上是让 \(a[l,r]\) 对 \(r + 1\) 取 \(\max\)。观察到 \(a\) 单调不减,故可以上线段树,先线段树上二分找到满足 \(a_i \le r + 1\) 的最小 \(i\),然后对 \(a[l,i]\) 进行区间赋值。
对于一次查询操作,仍然利用单调性,线段树上二分找到使得 \(a_i \le r,i\le l\) 的最大 \(i\),此时最优解为 \(p_r - p_i\)。对于 \([i+1,l]\) 这段区间,最优解为 \(\min(a_j-p_j)\),这个怎么维护呢? push_up 显然;区间推平时,\(a\) 都相等,\(p\) 必定取最大的 \(p\),也就是最右的 \(p\)。
时间复杂度 \(O(m \log n)\)
代码
#include <bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
#define mid ((l + r) >> 1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1e5 + 5,M = 100 + 5,mod = 998244353;
int pos[N];
int mn[N << 2],mx[N << 2],tag[N << 2];
int n,m;
void push_up(int p){
mn[p] = min(mn[ls(p)],mn[rs(p)]);
mx[p] = max(mx[ls(p)],mx[rs(p)]);
}
void add_tag(int p,int l,int r,int k){
tag[p] = k;
mx[p] = k;
mn[p] = pos[k] - pos[r];
}
void push_down(int p,int l,int r){
if(tag[p]){
add_tag(ls(p),l,mid,tag[p]);
add_tag(rs(p),mid + 1,r,tag[p]);
tag[p] = 0;
}
}
void build(int p,int l,int r){
tag[p] = 0;
if(l == r){
mx[p] = l + 1;
mn[p] = pos[l + 1] - pos[l];
return;
}
build(ls(p),l,mid),build(rs(p),mid + 1,r);
push_up(p);
}
int query(int p,int l,int r,int L,int R,int k){
if(l == r) return mx[p] >= k ? l : 2e9;
push_down(p,l,r);
if(mx[ls(p)] >= k){
return query(ls(p),l,mid,L,R,k);
}else{
return query(rs(p),mid + 1,r,L,R,k);
}
}
void modi(int p,int l,int r,int L,int R,int k){
if(l > R || r < L) return;
if(l >= L && r <= R){
add_tag(p,l,r,k);
return;
}
push_down(p,l,r);
modi(ls(p),l,mid,L,R,k),modi(rs(p),mid + 1,r,L,R,k);
push_up(p);
}
int ask(int p,int l,int r,int L,int R){
if(l > R || r < L) return 2e9;
if(l >= L && r <= R){
return mn[p];
}
push_down(p,l,r);
return min(ask(ls(p),l,mid,L,R),ask(rs(p),mid + 1,r,L,R));
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>pos[i];
}
pos[n + 1] = 2.1e9;
build(1,1,n);
while(m--){
int o;
cin>>o;
if(o == 1){
int l,r;
cin>>l>>r;
int k = query(1,1,n,l,r,r + 1) - 1;
if(k >= l){
modi(1,1,n,l,min(k,r),r + 1);
}
}else{
int l,r;
cin>>l>>r;
int k = query(1,1,n,l,r,r) - 1;
k = min(k,n);
int res = 2e9;
if(k){
res = pos[r] - pos[min(l,k)];
}
res = min(res,ask(1,1,n,k + 1,l));
cout<<(res > 1e9 ? -1 : res)<<'\n';
}
}
}
return 0;
}

浙公网安备 33010602011771号