2023牛客OI赛前集训营-提高组(第二场) 出租

题目大意

你有 n n n栋楼,编号为 1 ∼ n 1\sim n 1∼n,每栋楼都有 k k k个房间可以出租,一个房间只能住一个人。每个人都有一个喜好位置 x x x,表示他想要在 x ∼ x + d x\sim x+d x∼x+d这些楼中住下。

现在有 m m m次询问,每次询问给出两个数字 x , y x,y x,y,表示来了 y y y个喜好位置为 x x x的租户想要租房。如果 y y y为负数,则表示离开了 − y -y −y个喜好位置为 x x x的租户。保证离开后喜好位置为 x x x的租户不为负数。

对于每次询问,输出 Y E S YES YES或 N O NO NO表示你能否染每个租户分配到理想的房间。

你可以随时更换租户的房间,但前提是新房间也要符合租户的喜好。

1 ≤ n , m , d ≤ 5 × 1 0 5 , 0 ≤ k , y ≤ 1 0 9 , 1 ≤ x ≤ n − d 1\leq n,m,d\leq 5\times 10^5,0\leq k,y\leq 10^9,1\leq x\leq n-d 1≤n,m,d≤5×105,0≤k,y≤109,1≤x≤n−d

题解

我们考虑什么时候输出 N O NO NO。

当存在一段区间 [ l , r ] [l,r] [l,r],使得喜好位置(这里指 x x x,不是 x ∼ x + d x\sim x+d x∼x+d)在这段区间上的租户的人数大于 k × ( r − l + 1 + d ) k\times (r-l+1+d) k×(r−l+1+d)的时候,则无论如何都无法给这些租户安排理想的房间。

设喜好位置为 i i i的租户个数为 v i v_i vi,则有上文可得输出 N O NO NO的条件为存在区间 [ l , r ] [l,r] [l,r]使得 ∑ i = l r ( v i − k ) > k × d \sum_{i=l}^r(v_i-k)>k\times d ∑i=lr(vi−k)>k×d。

设 w i w_i wi表示喜好位置为 i i i的租户个数减去 k k k之后的值,即 v x − k v_x-k vx−k,则输出 N O NO NO的条件为存在区间 [ l , r ] [l,r] [l,r]使得 ∑ i = l r w i > k × d \sum_{i=l}^rw_i>k\times d ∑i=lrwi>k×d

用线段树维护 w i w_i wi的最大子段和,每次操作只需进行单点修改并将 [ 1 , n ] [1,n] [1,n]的最大子段和 k × d k\times d k×d比较大小即可。

时间复杂度为 O ( ( n + m ) log ⁡ n ) O((n+m)\log n) O((n+m)logn)。

code

cpp 复制代码
#include<bits/stdc++.h>
#define lc k<<1
#define rc k<<1|1
using namespace std;
int n,m,K,d;
long long tr[4000005],wl[4000005],wr[4000005],mx[4000005];
void build(int k,int l,int r){
	if(l==r){
		tr[k]=-K;
		return;
	}
	int mid=l+r>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	tr[k]=tr[lc]+tr[rc];
}
void ch(int k,int l,int r,int x,int y){
	if(l==r&&l==x){
		tr[k]+=y;
		wl[k]=wr[k]=max(0ll,tr[k]);
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) ch(lc,l,mid,x,y);
	else ch(rc,mid+1,r,x,y);
	wl[k]=max(wl[lc],tr[lc]+wl[rc]);
	wr[k]=max(wr[rc],tr[rc]+wr[lc]);
	mx[k]=max(wr[lc]+wl[rc],max(mx[lc],mx[rc]));
	tr[k]=tr[lc]+tr[rc];
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&K,&d);
	build(1,1,n);
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		ch(1,1,n,x,y);
		if(mx[1]<=1ll*K*d) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}
相关推荐
凌康ACG5 小时前
Sciter之c++与前端交互(五)
c++·sciter
郝学胜-神的一滴7 小时前
Linux命名管道:创建与原理详解
linux·运维·服务器·开发语言·c++·程序人生·个人开发
晚风(●•σ )7 小时前
C++语言程序设计——11 C语言风格输入/输出函数
c语言·开发语言·c++
恒者走天下9 小时前
秋招落定,拿到满意的offer,怎么提高自己实际的开发能力,更好的融入团队
c++
天若有情6739 小时前
【c++】手撸C++ Promise:从零实现通用异步回调组件,支持链式调用+异常安全
开发语言·前端·javascript·c++·promise
学困昇9 小时前
C++中的异常
android·java·c++
合作小小程序员小小店10 小时前
桌面安全开发,桌面二进制%恶意行为拦截查杀%系统安全开发3.0,基于c/c++语言,mfc,win32,ring3,dll,hook,inject,无数据库
c语言·开发语言·c++·安全·系统安全
Codeking__10 小时前
C++ 11 atomic 原子性操作
开发语言·c++
crescent_悦10 小时前
PTA L1-020 帅到没朋友 C++
数据结构·c++·算法
卡提西亚11 小时前
C++笔记-34-map/multimap容器
开发语言·c++·笔记