poj2528(线段树)

时间:2023-01-07 00:27:45

题目连接:http://poj.org/problem?id=2528

题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报

分析:离散化+线段树,这题因为每个数字其实表示的是一个单位长度,因此离散化后的每个点如果相邻数字间距大于1的话,得在其中加上任意一个数字。

否则 如 [1 10] [1 3] [5 10]这组数据能看见3种海报,而离散化后[1,3,5,10]对应[1,2,3,4],更新[1,2]再更新[3,4]就能看见两种海报了。所以离散化应为[1,2,3,4,5,9,10].

#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 200010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
bool has[N];
int le[N],ri[N];
int col[N<<],X[N];
int ans;
int bin(int key,int n,int a[])
{
int l=,r=n-;
while(l<=r)
{
int m=(l+r)>>;
if(a[m]==key)return m;
if(a[m]<key)l=m+;
else r=m-;
}
}
void Pushdown(int rt)
{
if(col[rt]!=-)
{
col[rt<<]=col[rt<<|]=col[rt];
col[rt]=-;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]=c;
return;
}
Pushdown(rt);
int m=(l+r)>>;
if(L<=m)update(L,R,c,lson);
if(m<R)update(L,R,c,rson);
}
void query(int l,int r,int rt)
{
if(l==r)
{
if(col[rt]!=-)
{
if(!has[col[rt]])ans++;
has[col[rt]]=true;
}
return;
}
Pushdown(rt);
int m=(l+r)>>;
query(lson);
query(rson);
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int nn=;
for(int i=;i<=n;i++)
{
scanf("%d%d",&le[i],&ri[i]);
X[nn++]=le[i];
X[nn++]=ri[i];
}
sort(X,X+nn);
int m=;
for(int i=;i<nn;i++)
if(X[i]!=X[i-])X[m++]=X[i];
for(int i=m-;i>;i--)
if(X[i]!=X[i-]+)X[m++]=X[i-]+;
sort(X,X+m);
FILL(col,-);
for(int i=;i<=n;i++)
{
int l=bin(le[i],m,X);
int r=bin(ri[i],m,X);
update(l+,r+,i,,m,);
}
ans=;FILL(has,false);
query(,m,);
printf("%d\n",ans);
}
}