poj 2528 线段树 离散化

本文介绍了一种使用线段树和离散化的方法来解决一个特定的问题:计算在一系列海报覆盖操作后,最终可见的海报种类数量。通过详细解释代码实现过程,帮助读者理解如何高效地解决此类问题。

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

题目连接:http://poj.org/problem?id=2528

题目大意:在一面墙上贴海报,墙很长,后面贴上去的海报要覆盖掉之前贴上去的海报,现在向墙上逐一的贴海报,问到最后墙上可以看见的海报有几种?

方法:线段树,离散化

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 10005
struct node
{
    int l, r, d;
}v[maxn<<2];
struct vir
{
    int val, pos;
    bool operator < (const vir& b)const
    {
        return val<b.val;
    }
}line[maxn<<2];
int set[maxn<<1][2], visited[maxn<<1], ans;
void build(int l, int r, int n)
{
    v[n].l = l, v[n].r = r;
    v[n].d = -1;
    if (l==r)
        return ;
    int mid = (v[n].l + v[n].r)>>1;
    build(l, mid, n<<1);
    build(mid+1, r, n<<1|1);
}
void pushdown(int n)
{
    if (v[n].d!=-1)
    {
        v[n<<1].d = v[n].d;
        v[n<<1|1].d = v[n].d;
        v[n].d = -1;
    }
}
void update(int l, int r, int n, int d)
{
    if (l<=v[n].l && v[n].r<=r)
    {
        v[n].d = d;
        return ;
    }
    pushdown(n);
    int mid = (v[n].l + v[n].r)>>1;
    if (r<=mid)
        update(l, r, n<<1, d);
    else if (l>mid)
        update(l, r, n<<1|1, d);
    else
    {
        update(l, mid, n<<1, d);
        update(mid+1, r, n<<1|1, d);
    }
}
void find(int l, int r, int n)
{
    if (v[n].d>=0 || l==r)
    {
        if (v[n].d>=0 && !visited[v[n].d])
        {
            visited[v[n].d] = 1;
            ++ ans;
        }
        return ;
    }
    pushdown(n);
    int mid = (v[n].l + v[n].r)>>1;
    find(l, mid, n<<1);
    find(mid+1, r, n<<1|1);
}
int main()
{
    int ncase, n;
    cin >> ncase;
    while (ncase--)
    {
        cin >> n;
        for (int i=0; i<n; ++i)
        {
            scanf("%d%d", &set[i][0], &set[i][1]);
            line[i<<1].val = set[i][0];
            line[i<<1].pos = -(i+1);
            line[i<<1|1].val = set[i][1];
            line[i<<1|1].pos = i+1;
        }
        sort(line, line+2*n);
        int tp = 1, temp = line[0].val;
        for (int i=0; i<2*n; ++i)//离散化
        {
            if (temp!=line[i].val)
            {
                ++ tp;
                temp = line[i].val;
            }
            if (line[i].pos < 0)
                set[ -line[i].pos-1 ][0] = tp;
            else
                set[ line[i].pos-1 ][1] = tp;
        }
        build(1, tp, 1);
        for (int i=0; i<n; ++i)
            update(set[i][0], set[i][1], 1, i);//更新
        memset(visited, 0, sizeof(visited));
        ans = 0;
        find(1, tp, 1);//统计
        printf("%d\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值