TOJ 4602 高橋和低橋 -- 線段樹 + 離散化

題目鏈接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4602

題目大意:給出n座橋的高度與m次洪水水位(一次洪水有漲水水位和退水水位兩個數據),問被淹次數不少於給定值k的橋的數量。(在某一次漲水前水位底於橋高,漲水後水位不底於橋高,則計該橋被淹一次)

分析:把橋高離散化後映射到1..kk(注意一個橋高可能對應多座橋,需記錄這個數據以便計算最終答案),每一次漲水時計算被淹的橋的高度區間(映射後的值),區間左端點爲漲水前水位,右端點爲漲水後水位,更新相應區間就好了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mp make_pair
#define X first
#define Y second
#define LL(x) ((x) << 1)
#define RR(x) ((x) << 1 | 1)
#define MEMSET(a, b) memset(a, b, sizeof(a))
using namespace std;

typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
typedef pair pii;
typedef vector vi;
typedef vi::iterator vi_it;
typedef map mii;
typedef priority_queue pqi;
typedef priority_queue, greater > rpqi;
typedef priority_queue pqp;
typedef priority_queue, greater > rpqp;

const int MAX_N = 100000 + 2;
int cnt[MAX_N];
int h[MAX_N];

struct
{
	int left;
	int right;
	int cnt;
	
	inline int mid() {
		return (left + right) >> 1;
	}
} st[MAX_N * 3];

void build(int l, int r, int idx)
{
	st[idx].left = l;
	st[idx].right = r;
	st[idx].cnt = 0;
	if (l != r) {
		int mid = st[idx].mid();
		build(l, mid, LL(idx));
		build(mid + 1, r, RR(idx));
	}
}

void update(int l, int r, int v, int idx)
{
	if (l <= st[idx].left && r >= st[idx].right) {
		st[idx].cnt += v;
		return;
	}
	
	int mid = st[idx].mid();
	if (l <= mid) {
		update(l, r, v, LL(idx));
	}
	if (r > mid) {
		update(l, r, v, RR(idx));
	}
}

int query(int pos, int idx)
{
	if (st[idx].left == st[idx].right) {
		return st[idx].cnt;
	}
	if (st[idx].cnt) {
		st[LL(idx)].cnt += st[idx].cnt;
		st[RR(idx)].cnt += st[idx].cnt;
		st[idx].cnt = 0;
	}
	int mid = st[idx].mid();
	if (pos <= mid) {
		return query(pos, LL(idx));
	}
	else {
		return query(pos, RR(idx));
	}
}

int main(int argc, char *argv[])
{
//	freopen("D:\\in.txt", "r", stdin);
	int n, m, k, a, b, i, cas = 1;
	while (cin >> n >> m >> k) {
		MEMSET(cnt, 0);
		for (i = 0; i < n; ++i) {
			scanf("%d", h + i);
		}
		sort(h, h + n);
		int kk = 1;
		cnt[0] = 1;
		for (i = 1; i < n; ++i) {
			if (h[i] == h[i - 1]) {
				++cnt[kk - 1];
			}
			else {
				cnt[kk] = 1;
				h[kk++] = h[i];
			}
		}
		build(0, kk - 1, 1);
		b = 1;
		while (m--) {
			scanf("%d", &a);
			int p1 = upper_bound(h, h + kk, b) - h;
			int p2 = upper_bound(h, h + kk, a) - h - 1;
			scanf("%d", &b);
			if (p2 >= p1) {
				update(p1, p2, 1, 1);
			}
		}
		int ans = 0;
		for (i = 0; i < kk; ++i) {
			if (query(i, 1) >= k) {
				ans += cnt[i];
			}
		}
		printf("Case %d: %d\n", cas++, ans);
	}
	return 0;
}

發佈了49 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章