http://poj.org/problem?id=2528
题目大意:
贴海报 有先后顺序
会发生覆盖 问你最后漏在外面的有几张海报
思路:
1.所给数据范围比较大,而且是以块为单位 所以首先要离散化排序+把块变成线
2.建树
3.按所给海报顺序进行贴海报 解决覆盖问题
4.搜索一遍 看看有哪些海报是漏在外面的 统计数量
代码及其注释:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
const int N=10005;
struct node1
{
int l,r;
}mem[N];//所给海报顺序 及其大小
struct node
{
int k;
int l,r;
}btree[N*10];//线段树
set<int>str;
bool cansee[N];//是否漏在外面
int a[N*2];
int I;
void build(int x,int i,int j)// 建树
{
btree[x].k=-1;
btree[x].l=i;//注意 l 不是直接表示左边界的大小范围 而是范围大小的下表
btree[x].r=j;
if(i+1==j)
return ;
int mid=(i+j)>>1;
build(x*2,i,mid);
build(x*2+1,mid,j);
}
void place(int x,int k,int l,int r)
{
if(a[btree[x].l]==l&&a[btree[x].r]==r)//如果正好覆盖这一块则不用往下搜了 否则会超时
{
btree[x].k=k;
return ;
}
if(btree[x].k>0)
{
btree[x*2].k=btree[x].k;//对应上面的 本来是一个整块现在被破坏了 需要把数据向下传
btree[x*2+1].k=btree[x].k;
btree[x].k=0;
}
int mid=a[(btree[x].l+btree[x].r)>>1];
if(l>=mid)
{
place(x*2+1,k,l,r);
}else if(r<=mid)
{
place(x*2,k,l,r);
}else
{
place(x*2,k,l,mid);
place(x*2+1,k,mid,r);
}
}
void find(int x)//最后搜一遍 并记录
{
cansee[btree[x].k]=true;
if(btree[x].l+1==btree[x].r||btree[x].k>0)
return ;
find(x*2);
find(x*2+1);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
str.clear();
for(int i=1;i<=n;++i)
{
scanf("%d %d",&mem[i].l,&mem[i].r);
++mem[i].r;//块变线
str.insert(mem[i].l);//用set自动 去重,排序
str.insert(mem[i].r);
}
I=0;
for(set<int>::iterator t=str.begin();t!=str.end();++t)
{
++I;a[I]=*t;//把set中的数据导入a数组中
}
build(1,1,I);//建树
for(int i=1;i<=n;++i)
{
place(1,i,mem[i].l,mem[i].r);//贴海报
}
memset(cansee,false,sizeof(cansee));
find(1);//搜索
int ans=0;
for(int i=1;i<=n;++i)
{
if(cansee[i])
++ans;
}
printf("%d\n",ans);
}
return 0;
}
浙公网安备 33010602011771号