顾名思义,是让每一个线段(海报)往上飘,美中不足的是有一点耗时
但是这个方法非常好懂,也很好实现,我还是要做一下记录的
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;
}
漂浮法用的空间较少,时间消耗较多,第一行是漂浮法,其它的应该是线段树的做法,而且用了离散化处理