“21 天好习惯”第一期-15

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;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值