poj 2528 Mayor's posters(线段树+离散化)

本文介绍了一道关于线段树与离散化的题目,通过覆盖线段的方法求最终可见线段的数量。文章详细解释了解决方案,包括离散化以减少内存使用,线段树上的染色操作及遍历计数等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://poj.org/problem?id=2528

(1)给定一条线段,依次在上面覆盖一些线段(左右位置已给定),求最终能看到的线段数(看到一部分也算)。

       本题的本质和染色问题一样,成段染色,延迟更新。

(2)有一个难点在于,所给定的区域是1到1000万,不可能开这么大的数组。况且,用于覆盖的线段只有1万条。

       这里用到了离散化方法,简化了问题,压缩了数组的大小(具体情况见代码)。

(3)傻到开了一个pos[]数组,准备用来表示谁映射到谁。。(很无语,当时没有注意pos[]数组要开到1000万这么大)。

(4)在写travel()函数时,忘了加上pushdown()。

(5)思路点拨:

    1)映射(离散化),降下内存使用量;

    2)染色操作;

    3)先消除所有的延迟标记(travel),再计量最终的颜色数,输出结果。

(6)熟悉映射的C++写法。

具体代码:

View Code
#include<stdio.h>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int maxn=101000;
int t, n, ans;
int num[maxn<<2];
int data[maxn];
int mark[maxn], color[maxn<<2];
struct node
{
    int a, b;
    node(int x, int y)
    {
        a=x;
        b=y;
    }
};
void pushdown(int rt)
{
    if(color[rt])
    {
        color[rt<<1]=color[rt<<1|1]=color[rt];
        color[rt]=0;
    }
}
void build(int l, int r, int rt)
{
    color[rt]=0;
    if(l==r)
    {
        mark[l]=0;
        return ;
    }
    int m=l+r>>1;
    build(lson);
    build(rson);
}
void update(int L, int R, int i, int l, int r, int rt)
{
    if(L<=l&&r<=R)
    {
        color[rt]=i;
        return ;
    }
    pushdown(rt);
    int m=l+r>>1;
    if(L<=m) update(L, R, i, lson);
    if(R>m) update(L, R, i, rson);
}
void travel(int l, int r, int rt)
{
    if(l==r)
    {
        mark[color[rt]]=1;
        return;
    }
    pushdown(rt);
    int m=l+r>>1;
    travel(lson);
    travel(rson);
}
int main()
{
    while(scanf("%d", &t)!=EOF)
    {
        while(t--)
        {
            scanf("%d", &n);
            vector<int>vec;
            vector<node>v;
            for(int i=0;i<n;i++)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                vec.push_back(x);
                vec.push_back(y);
                v.push_back(node(x, y));
            }
            sort(vec.begin(), vec.end());
            map<int, int>mp;
            int tm=1;
            for(int i=0;i<vec.size();i++)
            {
                if(mp.find(vec[i])==mp.end())
                    mp[vec[i]]=tm++;
            }
            build(1, n<<1, 1);
            for(int i=0;i<v.size();i++)
            {
                int x, y;
                x=mp[v[i].a];
                y=mp[v[i].b];
                update(x, y, i+1, 1, n<<1, 1);
            }
            ans=0;
            travel(1, n<<1, 1);
            for(int i=1;i<=(n<<1);i++)
            {
                if(mark[i]) ans++;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

 

 

转载于:https://www.cnblogs.com/tim11/archive/2012/08/27/2658155.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值