思路:
考虑如何合并两个相邻的区间,假色表示从
出发允许最早的时间,
表示从
出发允许最晚的时间,
表示从
到
需要的时间。
比较和
能否和并,其实只需要满足
。有没有其它的判断方式呢,有,但是没必要:
。(
这不是没事找事吗,主要是补题的时候想换个思路写,想通过维护一个和一个
来完成合并,画个图就知道这样比较冗余)。
所以我们需要维护区间的
,同时维护一个
表示
到
需要的时间,主要用来更新合并后的
。
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;
} 
京公网安备 11010502036488号