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


    题目大意

    你有 n n n栋楼,编号为 1 ∼ n 1\sim n 1n,每栋楼都有 k k k个房间可以出租,一个房间只能住一个人。每个人都有一个喜好位置 x x x,表示他想要在 x ∼ x + d x\sim x+d xx+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 1n,m,d5×105,0k,y109,1xnd


    题解

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

    当存在一段区间 [ l , r ] [l,r] [l,r],使得喜好位置(这里指 x x x,不是 x ∼ x + d x\sim x+d xx+d)在这段区间上的租户的人数大于 k × ( r − l + 1 + d ) k\times (r-l+1+d) k×(rl+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(vik)>k×d

    w i w_i wi表示喜好位置为 i i i的租户个数减去 k k k之后的值,即 v x − k v_x-k vxk,则输出 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

    #include
    #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;
    		mx[k]=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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    (附源码)python房屋租赁管理系统 毕业设计 745613
    云原生系列 二【轻松入门容器基础操作】
    第十三届蓝桥杯c++b组-积木画
    【图形学】18 光照模型(三、镜面反射的Shader实现)
    【408考点之数据结构】线性表的顺序表示
    < 今日份知识点:谈谈内存泄漏 及 在 Javascript 中 针对内存泄漏的垃圾回收机制 >
    数据分析:单元3 图像的手绘效果实现
    8月5日学习笔记 glibc安装与安全用户角色权限
    秋招/考研面试-操作系统
    JavaWeb简单实例——jQuery
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/133675910