您的位置:首页 > 其它

POJ2528Mayor's posters(离散化 + 线段树)

2016-03-02 20:26 337 查看
题目链接:

题意:给定一些高度都相同的海报去贴,问最后能看见几张海报

The picture below illustrates the case of the sample input.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int Max = 100000; //根据海报的个数来设置数组
struct node
{
int l,r;
int cover; //海报的编号
int tag;  //懒惰标志
};
node tree[Max * 8];
int t[4 * Max + 10],cnt,res[Max * 4 + 10];
int a[Max + 10],b[Max + 10];
void buildTree(int left, int right, int k)
{
tree[k].l = left;
tree[k].r = right;
tree[k].cover = 0;
tree[k].tag = -1;
if(left == right)
return;
int mid = (left + right) / 2;
buildTree(left, mid, k * 2);
buildTree(mid + 1, right, k * 2 + 1);
}
int Find(int l, int r, int key, int temp[])
{
while(r >= l)
{
int mid = (l + r) / 2;
if(temp[mid] == key)
return mid;
else if(temp[mid] > key)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
void upDate(int left, int right, int k, int num)
{
if(tree[k].l == left && tree[k].r == right)
{
tree[k].cover = num;
tree[k].tag = num;
return;
}
if(tree[k].tag != -1)
{
tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag;
tree[k * 2].cover = tree[k * 2 + 1].cover = tree[k].tag;
tree[k].tag = -1;
}
int mid = (tree[k].l + tree[k].r) / 2;
if(right <= mid)
{
upDate(left, right, k * 2, num);
}
else if(mid < left)
{
upDate(left, right, k * 2 + 1, num);
}
else
{
upDate(left, mid, k * 2, num);
upDate(mid + 1, right, k * 2 + 1, num);
}
}
void Search(int k)
{
if(tree[k].tag != -1)
{
tree[k].cover = tree[k].tag;
tree[k * 2].tag = tree[k * 2 + 1].tag = tree[k].tag;
tree[k * 2].cover = tree[k * 2 + 1].cover = tree[k].tag;
tree[k].tag = -1;
}

if(tree[k].l == tree[k].r)
{
res[ tree[k].cover ] = 1; // 看看每一个点的海报编号
return;
}
Search(k * 2);
Search(k * 2 + 1);
}
int main()
{
int test,n;
scanf("%d", &test);
while(test--)
{
scanf("%d", &n);
cnt = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i], &b[i]);
t[ cnt++ ] = a[i];
t[ cnt++ ] = b[i]; //将所有的端点都放入t中
}
sort(t, t + cnt);
int cnt1 = 1;
for(int i = 1; i < cnt; i++)
{
if(t[i] != t[i - 1])  //去掉相同的
t[ cnt1++ ] = t[i];
}
for(int i = cnt1 - 1; i > 0; i--)
{
if(t[i] - t[i - 1] > 1) //如果相邻数差值大于1,就则加一个数
t[ cnt1++ ] = t[i - 1] + 1;
}
sort(t, t + cnt1); //加完之后排序,此时已经离散完毕
for(int i = cnt1; i > 0; i--)
t[i] = t[i - 1];
//使区间为1到cnt1,好处理
buildTree(1, cnt1, 1);

for(int i = 1; i <= n; i++)
{
int left = Find(1, cnt1, a[i], t);  //二分查找出每个区间的端点在离散化后的数组中的位置
int right = Find(1, cnt1, b[i], t);
upDate(left, right, 1, i);  //更新,设置覆盖位为 i
}
memset(res, 0, sizeof(res));
Search(1); //从根开始查找
int ans = 0;
for(int i = 1; i <= n; i++)
if(res[i])
ans++;
printf("%d\n", ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: