題目鏈接: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;
}