题 意:小明有n个花瓶,可以进行m次两种操作,1 A F。小明收到F朵花,尝试从第A个开始插花。从A一直到….N,如果还有花剩下就丢弃。2 X Y:清空[x,y]种的花瓶,如果花瓶有花,则丢弃。对于询问1 每次输出最左边的端点和右边的端点。对于询问2每次
每次输出清空的区间内,有多少朵花。如果一朵花都不能插,就打印Can not put any one.
数据范围:
1<=n,m<=5e4+1
1<=x < y <= n
输入样例:
2
10 5
1 3 5
2 4 5
1 1 8
2 3 6
1 8 8
10 6
1 2 5
2 3 4
1 0 8
2 2 5
1 4 4
1 2 3
输出样例:
[pre]3 7
2
1 9
4
Can not put any one.
2 6
2
0 9
4
4 5
2 3
[/pre]
思 路:用线段树去维护每个区间空瓶的和。对于操作1,二分出left和right。之后就是简单的操作
收 获:学会了线段树和二分的结合。之前还学了线段树和dfs序的结合
#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 5e4+5;
const int mod = 10007;
int sum[maxn<<2],lazy[maxn<<2];
int n,m;
void PushUp(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int len){
if(lazy[rt]!=-1){
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum[rt<<1] = (len-(len>>1))*lazy[rt];
sum[rt<<1|1] = (len>>1)*lazy[rt];
lazy[rt] = -1;
}
}
void build(int l,int r,int rt){
lazy[rt] = -1;
if(l == r){
sum[rt] = 1;
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R){
return sum[rt];
}
PushDown(rt,r-l+1);
int m = (l+r)>>1,ans = 0;
if(L<=m) ans+=query(L,R,lson);
if(R>m ) ans+=query(L,R,rson);
return ans;
}
int findLeft(int x){
int r = n;
int l = x;
while(r>l){
int m = (l+r)>>1;
if(query(l,m,1,n,1)>=1)r=m;
else l = m+1;
}
return r;
}
int findRight(int x,int number){
int r = n;
int l = x;
while(r>l){
int m = (l+r)>>1;
if(query(x,m,1,n,1)>=number)r = m;
else l = m+1;
}
return r;
}
void update(int L,int R,int flag,int l,int r,int rt){
if(L<=l && r<=R){
sum[rt] =(r-l+1)*flag;
lazy[rt]=flag;
return;
}
PushDown(rt,r-l+1);
int m = (l+r)>>1;
if(L<=m ) update(L,R,flag,lson);
if(R>m ) update(L,R,flag,rson);
PushUp(rt);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
build(1,n,1);
int a,b,c;
for(int i=0;i<m;i++){
scanf("%d %d %d",&a,&b,&c);
if(a == 1){
b++;
int left,right;
int number = query(b,n,1,n,1);
if(number == 0){
printf("Can not put any one.\n");
continue;
}
left = findLeft(b);
right= findRight(b,min(number,c));
printf("%d %d\n",left-1,right-1);
update(left,right,0,1,n,1);
}else{
b++;c++;
int ans = query(b,c,1,n,1);
printf("%d\n",c-b+1-ans);
update(b,c,1,1,n,1);
}
}
printf("\n");
}
return 0;
}
/*
2
6 2 4
*/