Journey among Railway Stations
思路:
考虑如何合并两个相邻的区间,假色
m
i
n
(
L
1
)
{min(L_1)}
min(L1)表示从
L
1
{L_1}
L1出发允许最早的时间,
m
a
x
(
L
1
)
{max(L_1)}
max(L1)表示从
L
1
{L_1}
L1出发允许最晚的时间,
c
o
l
[
i
]
{col[i]}
col[i]表示从
i
{i}
i到
i
+
1
{i+1}
i+1需要的时间。
比较 [ L 1 , R 1 ] {[L_1,R_1]} [L1,R1]和 R 1 + 1 , R 2 {R_1+1,R_2} R1+1,R2能否和并,其实只需要满足 m i n ( R 1 ) + c o l [ R + 1 ] < = m a x ( R 1 + 1 ) {min(R_1)+col[R+1]<=max(R_1+1)} min(R1)+col[R+1]<=max(R1+1)。有没有其它的判断方式呢,有,但是没必要: m a x ( R 1 ) + c o l [ R + 1 ] < = m a x ( R 1 + 1 ) ∣ ∣ m i n ( R 1 ) + c o l [ R + 1 ] < = m a x ( R 1 + 1 ) {max(R_1)+col[R+1]<=max(R_1+1)||min(R_1)+col[R+1]<=max(R_1+1)} max(R1)+col[R+1]<=max(R1+1)∣∣min(R1)+col[R+1]<=max(R1+1)。(这不是没事找事吗,主要是补题的时候想换个思路写,想通过维护一个 m i n ( L 1 ) {min(L_1)} min(L1)和一个 m a x ( R 1 ) {max(R_1)} max(R1)来完成合并,画个图就知道这样比较冗余)。
所以我们需要维护区间 [ L , R ] {[L,R]} [L,R]的 m a x ( L ) , m i n ( R ) {max(L),min(R)} max(L),min(R),同时维护一个 s u m {sum} sum表示 L {L} L到 R {R} R需要的时间,主要用来更新合并后的 m a x ( L ) , m i n ( R ) {max(L),min(R)} max(L),min(R)。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7,mod=1e9+7;
struct node{
int _min,_max,sum;
}t[maxn<<2];
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int u[maxn],v[maxn],co[maxn];
node merge(node l,node r,int mid) {
node x;
x.sum=l.sum+r.sum+co[mid];
x._max=min(l._max,r._max-co[mid]-l.sum);//取上界的最小值
x._min=max(r._min,l._min+co[mid]+r.sum);//取下界的最大值
if(l._min+co[mid]>r._max) x._max=-1e9;//小区间不能合并,大区间也不能合并
return x;
}
inline void build(int l,int r,int rt) {
if(l==r) {
t[rt]._max=v[l];
t[rt]._min=u[r];//u[r]==u[l]
t[rt].sum=0;
return;
}
int mid=(l+r)/2;
build(lson);
build(rson);
t[rt]=merge(t[rt<<1],t[rt<<1|1],mid);
}
void update(int l,int r,int rt,int x) {
if(l==r) {
t[rt]._max=v[l];
t[rt]._min=u[r];//u[r]==u[l]
t[rt].sum=0;
return;
}
int mid=(l+r)/2;
if(mid>=x) update(lson,x);
else update(rson,x);
t[rt]=merge(t[rt<<1],t[rt<<1|1],mid);
}
node qry(int l,int r,int rt,int x,int y) {
if(l>=x&&r<=y) return t[rt];
int mid=(l+r)/2;
if(mid>=y) return qry(lson,x,y);
else if(mid<x) return qry(rson,x,y);
else return merge(qry(lson,x,y),qry(rson,x,y),mid);
}
inline void solve() {
int n;
cin>>n;
for(int i=1;i<=n;++i) cin>>u[i];
for(int i=1;i<=n;++i) cin>>v[i];
for(int i=1;i<n;++i) cin>>co[i];
build(1,n,1);
int Q,op,x,y;
cin>>Q;
while(Q--) {
cin>>op;
if(!op) {
cin>>x>>y;
node cur=qry(1,n,1,x,y);
if(cur._max<u[x]) cout<<"No\n";
else cout<<"Yes\n";
}
else if(op&1) {
cin>>x;
cin>>co[x];
update(1,n,1,x);
}
else {
cin>>x;
cin>>u[x]>>v[x];
update(1,n,1,x);
}
}
}
int main() {
ios::sync_with_stdio(0);cin.tie(nullptr);cout.tie(nullptr);
int _=1;
cin>>_;
while(_--) solve();
return 0;
}