漂浮法——线段树POJ2528

顾名思义,是让每一个线段(海报)往上飘,美中不足的是有一点耗时

但是这个方法非常好懂,也很好实现,我还是要做一下记录的

for(int i = 1;i <= n;i++)
            {
                scanf("%d%d",&l[i],&r[i]);
            }
            int ans = 0;
            for(int i = 1;i <= n;i++)
            {
                if(if_float(l[i],r[i],i + 1))ans++;
            }
按正常的输入方式,把每一个左右端点都进行存储

bool if_float(int le,int re,int i)
{

    while(i <= n && (re < l[i] || le > r[i]))i++;
    //飘出来了
    if(i > n)return true;
    if(le >= l[i] && re <= r[i])return 0;


    int ret = 0;

    if(le < l[i])ret = if_float(le,l[i] - 1,i + 1);
    if(!ret && re > r[i])ret = if_float(r[i] + 1,re,i + 1);
    return ret;

}

先进行漂浮测试——和每一个他后面要贴的海报进行比较,如果没有任何交集,漂浮成功,返回true
如果漂浮失败——看失败原因——如果是完全被覆盖那么直接false

如果仅仅是左/右被覆盖,那么就再漂浮左部分,如果左成功,右就不必再飘了

#include <iostream>
#include <string.h>
#define clr(x)  memset(x,0,sizeof(x))
#define clrmax(x)  memset(x,127,sizeof(x))
using namespace std;
const int Max = 1e5 + 10;
int l[Max],r[Max];
int t,n;
bool if_float(int le,int re,int i)
{

    while(i <= n && (re < l[i] || le > r[i]))i++;
    //飘出来了
    if(i > n)return true;
    if(le >= l[i] && re <= r[i])return 0;


    int ret = 0;

    if(le < l[i])ret = if_float(le,l[i] - 1,i + 1);
    if(!ret && re > r[i])ret = if_float(r[i] + 1,re,i + 1);
    return ret;

}
int main()
{

    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d",&n);
            for(int i = 1;i <= n;i++)
            {
                scanf("%d%d",&l[i],&r[i]);
            }
            int ans = 0;
            for(int i = 1;i <= n;i++)
            {
                if(if_float(l[i],r[i],i + 1))ans++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

漂浮法用的空间较少,时间消耗较多,第一行是漂浮法,其它的应该是线段树的做法,而且用了离散化处理


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值