码迷,mamicode.com
首页 > 编程语言 > 详细

hdu 5372 Segment Game(树状数组)

时间:2015-08-12 23:38:53      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 5372 Segment Game(树状数组)

标签:

原文地址:http://blog.csdn.net/keshuai19940722/article/details/47453423

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!