hdu 4614 Vases and Flowers (线段树 + 区间求和)

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/qq_35930475/article/details/80469212