您的位置:首页 > 编程语言 > C语言/C++

POJ 2528 线段树 成段更新+【离散化】 贴海报.cpp

2012-10-26 07:42 267 查看
[b]题意:[/b]

[b]  给出了n份海报的贴在board上的起始位置和结束位置[/b]

  问最后可以看到多少份海报

 

输入:

  n表示有n份海报

  接下来n行 每行 a b 表示海报占据了a~b的位置..

思路:

  线段树成段更新

  用树的结点value表示控制范围内的海报编号..

  因为不用更新到底+查询到每一个叶子节点..所以提高了查询和更新效率..

  其中因为海报长度给的很大..

  所以可以使用离散化来减少空间的消耗以及查询和更新时的递归次数..



[b]Tips:[/b]

[b]  因为给出的a b 表示的是在a~b内贴了海报..[/b]

  所以a b给的是值..但是表示的是一段范围..

  如果用正常的离散化..就可能出现

  最底下一层贴了一张海报AA..

  然后上面贴了两张相邻的海报BB 和 CC

  BB.r < CC.l

  但是离散化后因为BB和CC是相邻的..所以BB.r = CC.l

  这样~本来两张海报之间是有空隙的..可以透过空隙看到AA

  结果离散化之后就覆盖了那个空隙..

  解决方法就是当发现相隔的两个海报之间的距离>1就在中间加一个数..

离散化的处理方式很有趣吖~~^^

View Code

#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 40010;
int lazy[MAXN<<2];
int arr[MAXN];
int vis[10000010];
int s[MAXN];
int cnt;

struct Node
{
int r;
int l;
}node[MAXN];

void pushDown(int rt)
{
if(lazy[rt] != -1) {
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
lazy[rt] = -1;
}
}

void modify(int l, int r, int x, int L, int R, int rt)
{
if(l <= L && r >= R) {
lazy[rt] = x;
return;
}
pushDown(rt);
int mid = (L+R) >> 1;
if(l <= mid) modify(l, r, x, L, mid, rt<<1);
if(mid < r) modify(l, r, x, mid+1, R, rt<<1|1);
}

int solve(int key, int tot, int *arr)
{
int mid;
int l = 0, r = tot-1;
while(l <= r) {
mid = (l+r)>>1;
if(arr[mid] == key) return mid;
if(arr[mid] > key) r = mid-1;
else l = mid+1;
}
}

void query(int l, int r, int rt)
{
if(lazy[rt] != -1) {
if(vis[lazy[rt]] == 0)
cnt++;
vis[lazy[rt]] = 1;
return;
}
if(l == r) return;
int mid = (l+r)>>1;
query(l, mid, rt<<1);
query(mid+1, r, rt<<1|1);
}

int main()
{
int i, j, k;
int n, T;
int tot, l, r;
while(scanf("%d", &T) != EOF)
while(T--)
{
memset(vis, 0, sizeof(vis));
memset(lazy, 0xff, sizeof(lazy));
tot = cnt = 0;

scanf("%d", &n);
for(i = 0; i < n; ++i) {
scanf("%d %d", &l, &r);
if(vis[l] == 0){
vis[l] = 1;
s[tot++] = l;
}
if(vis[r] == 0) {
s[tot++] = r;
vis[r] = 1;
}
node[i].l = l, node[i].r = r;
}

sort(s, s+tot);

for(i = tot-1; i > 0; --i) {
if(s[i] - s[i-1] > 1)
s[tot++] = s[i-1]+1;
}
sort(s, s+tot);

for(i = 0; i < n; ++i) {
l = solve(node[i].l, tot, s);
r = solve(node[i].r, tot, s);
modify(l, r, i, 0, tot, 1);
}
memset(vis, 0, sizeof(vis));
query(0, tot, 1);
printf("%d\n", cnt);
}
return 0;
}




[b]题目链接:http://poj.org/problem?id=2528[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: