poj2528

线段树,线段树一般是对连续的区块进行操作,每次给出相应的区块,但是本题给出海报覆盖的是区间,要把区间对应到区块上。虽然有些情况还不能处理,但是过了。

View Code
#include <iostream>
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<algorithm>
using namespace std;

#define maxn 20005

struct Interval
{
int s, e;
}interval[maxn];

struct Node
{
Node
*pleft, *pright;
int l, r;
bool full;
}tree[maxn
* 3];

int pos[maxn * 2], poscount, ncount;

void buildtree(Node *proot, int l, int r)
{
proot
->l = l;
proot
->r = r;
if (l == r)
return;
int mid = (l + r) / 2;
ncount
++;
proot
->pleft = tree + ncount;
ncount
++;
proot
->pright = tree + ncount;
buildtree(proot
->pleft, l, mid);
buildtree(proot
->pright, mid + 1, r);
}

bool paste(Node *proot, int l, int r)
{
if (l == r)
return false;
if (proot->full)
return false;
if (proot->l == l && proot->r == r - 1)
{
proot
->full = true;
return true;
}
int mid = (proot->l + proot->r) / 2;
bool ret;
if (r <= mid + 1)
ret
= paste(proot->pleft, l, r);
else if (l > mid)
ret
= paste(proot->pright, l, r);
else
{
ret
= paste(proot->pleft, l, mid + 1);
ret
= paste(proot->pright, mid + 1, r) || ret;
}
proot
->full = proot->pleft->full && proot->pright->full;
return ret;
}

int binarysearch(int a)
{
int l = 0;
int r = poscount - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (pos[mid] >= a)
r
= mid;
else
l
= mid + 1;
}
return l;
}

int main()
{
//freopen("t.txt", "r", stdin);
int t;
scanf(
"%d", &t);
while (t--)
{
poscount
= 0;
ncount
= 0;
memset(tree,
0, sizeof(tree));
int n;
scanf(
"%d", &n);
for (int i = 0; i < n; i++)
{
scanf(
"%d%d", &interval[i].s, &interval[i].e);
pos[poscount
++] = interval[i].s;
pos[poscount
++] = interval[i].e;
}
sort(pos, pos
+ poscount);
poscount
= unique(pos, pos + poscount) - pos;
buildtree(tree,
0, poscount - 1);
int ans = 0;
for (int i = n - 1; i >= 0; i--)
{
int s = binarysearch(interval[i].s);
int e = binarysearch(interval[i].e) + 1;
if (paste(tree, s, e))
ans
++;
}
printf(
"%d\n", ans);
}
return 0;
}

posted @ 2011-05-17 20:51  金海峰  阅读(870)  评论(1编辑  收藏  举报