这题数据很大,数组开不下,要离散化,把输入的区间离散化,映射到相应的小区间,就可以了。离散的时候注意,这是区间离散后会出现些问题,所以离散时将区间差大于1的数后面插入一个数,保证离散正确化,离散的方法,排序,去重,在二分查找,将对应的数组索引作为新的端点。
这里,标记=0表示没有贴,标记大于0 表示贴了,并且不同标记代表不同海报,不断更新,最后查询,将海报数输出。
/*
poj 2528
该死的 海报板
n太大了,得离散化 不能普通的离散,使离散区间大一点,所以,在区间大于1的两个数间插个数,隔开些
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define MAX 12000
using namespace std;
//int sum[MAX];
int mark[MAX<<4];
int vis[MAX<<1];
int h[MAX<<1];
int w[MAX<<1];
int v[MAX<<2];
int ans =0;
void change_down(int T)
{
if (mark[T])//
{
mark[T<<1] = mark[T<<1|1] = mark[T];
mark[T]=0;
}
}
void update(int T,int s,int e,int p,int l,int r)
{
if (s<= l && e>=r)
{
mark[T] = p;
return;
}
else
{
change_down(T);
int mid = (l + r)>>1;
if (s<=mid) update(T<<1,s,e,p,l,mid);
if (e>mid) update(T<<1|1,s,e,p,mid+1,r);
}
}
void Query (int T,int l,int r)
{
if (mark[T])
{
if (!vis[mark[T]])
{
vis[mark[T]] = 1;
ans++;
}
return;
}
if (l==r) return ;
change_down(T);
int mid = (l+r)>>1;
Query(T<<1,l,mid) ;
Query(T<<1|1,mid+1,r);
}
int main ()
{
int T;
int n,a1,b1;
scanf ("%d",&T);
while(T--)
{ memset (mark,0,sizeof(mark));
memset(vis,0,sizeof (vis));
scanf ("%d",&n);
int k=0;
for (int i=0;i<n;++i)
{
scanf ("%d%d",&h[i],&w[i]);
v[k++]=h[i];v[k++]=w[i];
}
sort(v,v+k);
int size = unique(v,v+k)-v;
for (int i=0;i<n ;++i)
{
a1 = lower_bound(v,v+size,h[i])-v+1;//这里小心了是去重后的大小
b1 = lower_bound(v,v+size,w[i])-v+1;//别写成K了, 去重后,元素个数变了,记住
//printf ("%d %d\n",a1,b1); //要不然你就 一直Runtime Error 吧
update(1,a1,b1,i+1,1,size); //wtf !!!!!
}
ans = 0;
Query(1,1,size);
printf ("%d\n",ans);
}
return 0;
}
/*
1
5
1 4
2 6
8 10
3 4
7 10
*/