题目链接:hdu 4614
思路:给你一段区间,区间每个点代表每个瓶子,两种状态,有话和无花,题目有两种询问,第一是询问你给你一个起点A和花的数,问你将从点A开始连续地插花直到没有空瓶或者已将插了B只(这里地连续并不是区间连续,而是相对于空瓶子来说地)。让你返回两个数,第一是你插花地第一个位置,第二个是你插花地最后一个位置。第二个查询是,给你A,B,让你先清空这段区间地花,并返回一个num表示你清空了多少只花。
我们可以用1代表空瓶子,0代表已经插了花地瓶子。为什么用1代表空而不是1呢,原因在于第一个询问我们需要知道线段树每段区间中地空瓶子总数,方便查询。
然后是查询插花位置地函数在下面的代码中,很难说,看代码理解吧。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
#define mid (L + R)/2
#define ls rt*2
#define rs rt*2+1
#define lson ls,L,mid
#define rson rs,mid+1,R
const int mx = 1e5+5;
int tree[mx<<2];
int lazy[mx<<2];
void build(int rt, int L, int R)
{
lazy[rt] = -1;
if(L == R) {
tree[rt] = 1;
return ;
}
build(lson);
build(rson);
tree[rt] = tree[ls] + tree[rs];
}
void pushDown(int rt, int L, int R)
{
if(lazy[rt] != -1){
tree[ls] = lazy[rt]*(mid - L + 1);
tree[rs] = lazy[rt]*(R - mid);
lazy[ls] = lazy[rs] = lazy[rt];
lazy[rt] = -1;
}
}
void upDate(int rt, int L, int R, int l, int r, int c)
{
if(l <= L && R <= r){
tree[rt] = c*(R - L + 1);
lazy[rt] = c;
return ;
}
pushDown(rt,L,R);
if(r <= mid) upDate(lson,l,r,c);
else if(l > mid) upDate(rson,l,r,c);
else{
upDate(lson,l,mid,c);
upDate(rson,mid+1,r,c);
}
tree[rt] = tree[ls] + tree[rs];
}
int query(int rt, int L, int R, int l, int r)
{
if(r < L || l > R) return 0;
if(l <= L && R <= r){
return tree[rt];
}
pushDown(rt, L, R);
if(r <= mid) return query(lson,l,r);
else if(l > mid) return query(rson,l,r);
else {
return query(lson,l,mid) + query(rson,mid+1,r);
}
}
int find(int rt, int L, int R, int l, int r, int num)
{
if(L == R)
return L;
pushDown(rt, L, R);
int res = query(lson,l,r);
if(res >= num) find(lson,l,r,num);
else find(rson,l,r,num-res);
}
int main()
{
int t, a, b, c;
scanf("%d", &t);
while(t--){
int n, m;
scanf("%d%d", &n ,&m);
build(1,0,n-1);
for(int i = 0; i < m; i++){
scanf("%d%d%d",&a, &b, &c);
if(a == 1){
int res = query(1,0,n-1,b,n-1);
if(res == 0){
printf("Can not put any one.\n");
upDate(1,0,n-1,b,n-1,0);
}
else{
int l = find(1,0,n-1,b,n-1,1);
int r = find(1,0,n-1,b,n-1,min(c,res));
printf("%d %d\n",l,r);
upDate(1,0,n-1,l,r,0);
}
}
else if(a == 2){
int res = query(1,0,n-1,b,c);
upDate(1,0,n-1,b,c,1);
printf("%d\n",c-b+1-res);
}
}
printf("\n");
}
return 0;
}