hdu 5372 Segment Game(树状数组)

题目链接:hdu 5372 Segment Game


因为线段长度是递增的,不会出现后面的线段被前面的线段完全覆盖,所以只要分别计算[1,l-1]之间有多少个左端点,[1,r]之间有多少个右端点,想减即可。


#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 2 * 1e5 + 5;
#define lowbit(x) ((x)&(-x))

struct Bit {
	int n, fenw[maxn];

	void init (int k) {
		n = k;
		memset(fenw, 0, (n + 1) * sizeof(int));
	}

	void add (int x, int d) {
		while (x <= n) {
			fenw[x] += d;
			x += lowbit(x);
		}
	}

	int sum (int x) {
		int ret = 0;
		while (x) {
			ret += fenw[x];
			x -= lowbit(x);
		}
		return ret;
	}
}L, R;

int N, Q, op[maxn], l[maxn], r[maxn], ID[maxn];
int cntL, cntR, left[maxn], right[maxn];

void init () {
	Q = cntL = cntR = 0;
	for (int i = 1; i <= N; i++) {
		scanf("%d%d", &op[i], &l[i]);

		if (op[i] == 0) {
			ID[++Q] = i;
			r[i] = l[i] + Q;
			left[cntL++] = l[i];
			right[cntR++] = r[i];
		}
	}

	sort(left, left + cntL);
	cntL = unique(left, left + cntL) - left;
	sort(right, right + cntR);
	cntR = unique(right, right + cntR) - right;

	L.init(cntL);
	R.init(cntR);
}

void solve () {
	for (int i = 1; i <= N; i++) {
		if (op[i]) {
			int v = ID[l[i]];
			int p = lower_bound(left, left + cntL, l[v]) - left + 1;
			int q = lower_bound(right, right + cntR, r[v]) - right + 1;
			L.add(p, -1);
			R.add(q, -1);
			Q++;
		} else {
			int p = lower_bound(left, left + cntL, l[i]) - left + 1;
			int q = lower_bound(right, right + cntR, r[i]) - right + 1;
			int ans = R.sum(q) - L.sum(p-1);
			L.add(p, 1);
			R.add(q, 1);
			printf("%d\n", ans);
		}
	}
}

int main () {
	int cas = 1;
	while (scanf("%d", &N) == 1) {
		init ();
		printf("Case #%d:\n", cas++);
		solve ();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值