『STA - R4』冰红茶 题解

Solution

首先发现性质:每一个 bot 只会被击毁一次。联想到小清新线段树,考虑维护每一个点最后喝的 ds 饮料数量,并同时维护区间 Max 和区间内被删除的点的数量 cnt

那么 3 操作只需回答 nw1 即可,执行 2 操作时需要判断某一个区间的点内是否被全部删除以及 Max 是否大于等于 k,如果满足才继续递归。

void modify(int u,int l,int r,int k){ 
	if(tr[u].l==tr[u].r){
		if(tr[u].Max>=k){ 
			tr[u].Max=-1e18; 
			tr[u].w=1; 
		} return ; 
	} pushdown(u); 
	int mid=tr[u].l+tr[u].r>>1; 
	if(l<=mid&&tr[u<<1].Max>=k&&tr[u<<1].w<(tr[u<<1].r-tr[u<<1].l+1)) modify(u<<1,l,r,k); 
	if(r>mid&&tr[u<<1|1].Max>=k&&tr[u<<1|1].w<(tr[u<<1|1].r-tr[u<<1|1].l+1)) modify(u<<1|1,l,r,k); 
	pushup(u); 
} 

维护 1 操作即是将喝同种饮料的 bot 的饮料数量加上 k,喝不同种饮料的 bot 的饮料数量赋值为 k,也就是区间加与区间覆盖。

唯一的难点在于分类讨论,考虑记录上一次 1 操作的 [l,r],那么有两种情况:

  1. 如果两个区间不相交,便将区间 [l,r],[l,r] 赋值为 k,其他 bot 加上 k

  2. 如果两个区间相交,则将相同部分加上 k,不相交部分赋值为 k,其余 bot 加上 k

	while(m--){ 
		int opt=read(),l,r,k; 
		if(opt==3) printf("%lld\n",n-tr[1].cnt);
		else{ 
			l=read(),r=read(),k=read(); 
			if(opt==2) modify(1,l,r,k); 
			else{ 
				modify_add(1,1,n,k); 
				if(lst.x){ 
					if(check(l,r,lst)) modify_tag(1,l,r,k),modify_tag(1,lst.x,lst.y,k);  
					else{ 
						int L=min(l,lst.x),R=max(r,lst.y); 
						int LL=max(l,lst.x),RR=min(r,lst.y); 
						modify_tag(1,L,LL-1,k),modify_tag(RR+1,R,k); 
					} 
				} lst={l,r}; 
			} 
		} 
	} 
posted @   Celestial_cyan  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示