(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
原题目描述在最下面。
两种操作,1:把 b b 朵花,从 a a 开始一个位置放一瓶,若该位置有花则跳过,每次输出插入花朵的起点的终点。若没有位置可以插花,则输出 Cannotputanyone. C a n n o t p u t a n y o n e . 。2:把 a a 到 b b 位置的花瓶清空,并输出之前这个区间内有多少朵花。
lazy=1 l a z y = 1 表示子区间内所有花瓶都可以插花, lazy=0 l a z y = 0 表示区间内所有花瓶都被插满了,初始化 lazy=−1 l a z y = − 1 。
sum s u m 表示区间内可以插花的数量。
这样定义就很好写 pushdown p u s h d o w n 和 pushup p u s h u p 了。
这题麻烦在于需要二分。对于操作1,先二分找出第一个可以插花的位置,若找不到则输出那句话。然后要二分终点的位置,这时还要区分这个区间能不能插满 b b 朵花。若可以插满则直接二分插入满 b b 朵花的终点就好,若不能插满则二分最后一个可插的位置。
#include
#include
#include
#include
#include
#include
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = (int)1e5 +107;
int n, m;
struct lp{
int l, r;
int lazy;//lazy==1表示下面都可以插,lazy==0表示都被插了,lazy==-1表示未被更新
int sum;//可插的数量,叶子节点为被插就是1
}cw[N<<2];
inline void push_up(int rt){
cw[rt].sum = cw[lson].sum+cw[rson].sum;
}
void build(int l,int r,int rt){
int mid = (l + r)>>1;
cw[rt].l=l;cw[rt].r=r;
cw[rt].lazy=-1;
if(l==r){
cw[rt].sum = 1;
return;
}
build(l,mid,lson);build(mid+1,r,rson);
push_up(rt);
}
void push_down(int rt){
if(cw[rt].lazy!=-1){
cw[lson].lazy=cw[rson].lazy=cw[rt].lazy;
cw[lson].sum=(cw[lson].r-cw[lson].l+1)*cw[rt].lazy;
cw[rson].sum=(cw[rson].r-cw[rson].l+1)*cw[rt].lazy;
cw[rt].lazy=-1;
}
}
void update(int L,int R,int c,int rt){
int l=cw[rt].l,r=cw[rt].r,mid=(l+r)>>1;
if(L<=l&&r<=R){
cw[rt].lazy = c;
cw[rt].sum = c*(r-l+1);
return;
}
if(cw[rt].l==cw[rt].r)return;
push_down(rt);
if(L>mid)update(L,R,c,rson);
else if(R<=mid)update(L,R,c,lson);
else{
update(L,mid,c,lson),update(mid+1,R,c,rson);
}
push_up(rt);
}
int query(int L,int R,int rt){
int l=cw[rt].l,r=cw[rt].r,mid=(l+r)>>1;
if(L<=l&&r<=R){
return cw[rt].sum;
}
if(cw[rt].l==cw[rt].r)return 0;
push_down(rt);
int sum = 0;
if(L>mid)sum = query(L,R,rson);
else if(R<=mid)sum = query(L,R,lson);
else{
sum = query(L,mid,lson)+query(mid+1,R,rson);
}
return sum;
}
int main(){
int tim;
scanf("%d",&tim);
while(tim--){
scanf("%d%d",&n,&m);
build(1,n,1);
int op,x,y;
while(m--){
scanf("%d%d%d",&op,&x,&y);
if(op==1){
++x;
int l = x,r = n,st = -1,ed = n,mid;
while(l<=r){
mid = (l+r)>>1;
if(query(x,mid,1)>=1){
st=mid;
r=mid-1;
}else{
l=mid+1;
}
}
if(st==-1){
printf("Can not put any one.\n");
continue;
}
l = st,r = n;
if(query(l,r,1)>=y){
while(l<=r){
mid = (l+r)>>1;
if(query(st,mid,1)>=y){
ed = mid;
r = mid-1;
}else{
l = mid+1;
}
}
}else{
while(l<=r){
mid = (l+r)>>1;
if(query(mid,n,1)>=1){
l = mid+1;
ed = mid;
}else{
r = mid-1;
}
}
}
printf("%d %d\n", st-1,ed-1);
update(st,ed,0,1);
}else{
printf("%d\n", y-x+1- query(x+1,y+1,1));
update(x+1,y+1,1,1);
}
}
puts("");
}
return 0;
}