线段树与二分操作 vases and flowers ——hdu 4614

操作1,的关键是找到第一只和最后一只空花瓶,完全可以利用二分法查找,找第一只花瓶可以在[X,N]内查找,第一个位置pos1,最后一只花瓶则在[POS1,N]中找,然后更新[POS1,POS2],全部置1即可
代码:

#include<iostream>
using namespace std;
const int N = 5e4 + 5;
struct node {
	int lazy;
	int sum;  //sum代表空花瓶的数量
}tree[N<<2];

int ls(int i) { return i << 2; }
int rs(int i) { return i << 2 | 1; }

int t, n, m, x, y, k;

//以下四个函数都是线段树的基本操作
void pushdown(int id, int l, int r) {
	if (tree[id].lazy == -1) { return; }

	int mid = (l + r) >> 1;

	tree[ls(id)].sum = (mid - l + 1) * tree[id].lazy;
	tree[rs(id)].sum = (r - mid) * tree[id].lazy;
	tree[ls(id)].lazy = tree[rs(id)].lazy = tree[id].lazy;

	tree[id].lazy = -1;
}

void pushup(int id) {
	tree[id].sum = tree[ls(id)].sum + tree[rs(id)].sum;
}

void build(int id, int l, int r) {
	if (l == r) {
		tree[id].lazy = -1;
		tree[id].sum = 0;
	}
	int mid = (l + r) >> 1;
	build(ls(id), l, mid);
	build(rs(id), mid + 1, r);
	tree[id].lazy = -1;
	pushup(id);
}

int query(int id, int l, int r, int x, int y) {
	if (x <= l && y >= r) return tree[id].sum;
	int ans = 0;
	pushdown(id, l, r);
	int mid = (l + r) >> 1;
	if (x <= mid) ans += query(ls(id), l, mid, x, y);
	if (y > mid) ans += query(rs(id), mid + 1, r, x, y);
	return ans;
}

void update(int id, int l, int r, int x, int y, int d) {  //d=1代表花瓶是空的,d=0代表花瓶是满的
	if (x <= l && y >= r) {
		tree[id].sum = (r - l + 1) * d;
		tree[id].lazy = d;
		return;
	}
	pushdown(id, l, r);
	int mid = (l + r) >> 1;
	if (x <= mid) update(ls(id), l, mid, x, y, d);
	if (y > mid) update(rs(id), mid + 1, r, x, y, d);
	pushup(id);
}

int binarysearch(int x, int n, int f) {
	int l = x, int r = n;
	while (l < r) {
		int mid = (l + r) >> 1;
		int t = query(1, 1, n, x, mid); //查找左边部分,从左边判断第f个空花瓶是在左边还是右边
		if (t >= f) r = mid;
		else l = mid + 1;
	}
	return r;
}

int main() {
	cin >> t;
	while (t--) {
		cin >> n >> m;
		build(1, 1, n);
		for (int i = 1; i <= m; i++) {
			cin >> k >> x >> y;
			if (k == 1) {
				x++;  //保证区间为[1,N]
				//首先查询[X,N]中是否有空花瓶
				int t = query(1, 1, n, x, n);
				if (t == 0) {
					cout << "Can not put any one" << endl;
				}
				else {
					t = min(y, t);  //计算需要插花数量,此时的y代表收到花的数量
					int s = binarysearch(x, n, 1);  //搜索第一个空花瓶
					int t = binarysearch(s, n, t);  //搜索最后一个空花瓶
					cout << s - 1 << " " << t - 1 << endl;
					update(1, 1, n, s, t, 0);
				}
			}
			else {
				x++; y++;
				int t = query(1, 1, n, x, y);
				update(1, 1, n, x, y, 1);
				cout << y - x + 1 - t;
			}
		}
		cout << endl;
	}
	return 0;
}
posted @ 2024-09-12 10:40  小明算法嘎嘎猛  阅读(6)  评论(0编辑  收藏  举报