『STA - R4』冰红茶 题解
Solution
首先发现性质:每一个 bot 只会被击毁一次。联想到小清新线段树,考虑维护每一个点最后喝的 ds 饮料数量,并同时维护区间 \(Max\) 和区间内被删除的点的数量 \(cnt\)。
那么 \(3\) 操作只需回答 \(n-w_1\) 即可,执行 \(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']\),那么有两种情况:
-
如果两个区间不相交,便将区间 \([l,r],[l',r']\) 赋值为 \(k\),其他 bot 加上 \(k\)。
-
如果两个区间相交,则将相同部分加上 \(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};
}
}
}

浙公网安备 33010602011771号