poj 2528 (线段树+离散化)

本文详细介绍了如何解决POJ2528问题,即通过贴报纸算法优化来求解最后能看见多少张贴纸。文章讨论了如何避免内存溢出,通过映射和构建树状结构来高效解决问题。

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

poj 2528

For each input data set print the number of visible posters after all the posters are placed. 

The picture below illustrates the case of the sample input. 

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4

题意:贴报纸,可以互相覆盖,求最后能看见多少。

数据很大,不离散会超出内存。将浪费的部分去掉,将出现过的所有点其映射到相距更近的点上。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define N 100005
#define mod 258280327
#define MIN 0
#define MAX 1000001

int l[N],r[N];
int x[N];
int has[10000005];

struct node
{
    int le,re;
    bool covered;
} pnode[10*N];

void build(int i,int l,int r)
{
    pnode[i].le = l;
    pnode[i].re = r;
    pnode[i].covered = false;
    if(l == r)
        return;

    build(2 * i,l,(l+r)/2);
    build(2*i+1,(l+r)/2+1,r);
}

bool insert(int i,int l,int r,int a,int b)//是否可见
{
    if(pnode[i].covered == true)//如果要找的已经被覆盖
        return false;
    if(l == a && r == b)
    {
        pnode[i].covered = true;
        return true;
    }

    bool ans;
    int mid = (l + r)>>1;
    if (mid >= b)
        ans = insert(i*2,l, mid,  a, b);
    else if (mid < a)
        ans = insert(i*2+1,mid+1, r, a, b);
    else
    {
        bool x1 = insert(i*2,l, mid, a, mid);
        bool x2 = insert(i*2+1,mid+1, r, mid+1, b);
        ans = x1 || x2;
    }

    if(pnode[i*2].covered == true && pnode[i*2+1].covered == true)
        pnode[i].covered = true;
    return ans;
}




int main()
{
    int T,n,tot;
    scanf("%d",&T);

    while(T--)
    {
        scanf("%d",&n);
        tot = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d",&l[i],&r[i]);
            x[tot++] = l[i];
            x[tot++] = r[i];
        }

        sort(x,x+tot);
        tot = unique(x,x+tot)-x;
        int all=1;
        for(int i = 0;i < tot;i++)
        {
            has[x[i]] = all;
            if(i < tot - 1)
            {
                if(x[i+1] - x[i] == 1)
                    all++;
                else
                    all+=2;
            }
        }

        build(1,1,all);
        int num = 0;

        for(int i = n;i >=1;i--)
        {
            if(insert(1,1,all,has[l[i]],has[r[i]]))
                num ++;
        }

        printf("%d\n",num);

    }
    return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值