版权声明:欢迎转载,转载请注明出处,如有错误,还望指出,谢谢 博客地址:https://blog.csdn.net/lanyanzhiji123asd https://blog.csdn.net/lanyanzhiji123asd/article/details/89645135
poj2528
/*
poj2528 贴海报,后面贴的会覆盖前面贴的,问最后有多少张海报不会完全被覆盖
1、首先因为数据很大1e7 ,所以我们离散化处理
2、我们从后往前判断,因为后面的一定不会被覆盖
3、我判断的时候是从最上面的区间开始,只要其中有一段区间还没贴海报,说明这段这张海报不会被完全覆盖
4、我用了pushdown和pushup
pushdown 如果当前区间被覆盖,他下面的左右节点也被覆盖
pushup 如果他的左右节点都被覆盖,那么他也被覆盖
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
#define ll long long
const int maxn=200005;
struct node
{
int left,right,val;
}tree[4*maxn];
int a[maxn],b[maxn],un[maxn],id[10000005];
void build(int L,int R,int num)
{
tree[num].left=L;
tree[num].right=R;
tree[num].val=0;
if(L==R)
return ;
int mid=(L+R)/2;
build(L,mid,num*2);
build(mid+1,R,num*2+1);
}
void pushdown(int num)
{
if(tree[num].val)
{
tree[num*2].val=1;
tree[num*2+1].val=1;
}
}
void pushup(int num)
{
if(tree[num*2].val&&tree[num*2+1].val)
tree[num].val=1;
}
int post(int L, int R,int num)
{//cout<<L<<" "<<R<<" "<<tree[num].left<<" "<<tree[num].right<<endl;
int ans=0;
if(tree[num].left>=L&&tree[num].right<=R)
{
if(!tree[num].val)
{
tree[num].val=1;
return 1;
}
else return 0;
}
pushdown(num);
int mid=(tree[num].left+tree[num].right)/2;
//进入他的左右节点判断,只要有一个没有被覆盖我们就可以返回1, ans就是1
if(L<=mid)
{
if(post(L,R,num*2))
ans=1;
}
if(R>mid)
{
if(post(L,R,num*2+1))
ans=1;
}
pushup(num);
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
int t,n,cnt,ans,i;
scanf("%d",&t);
while(t--)
{
cnt=0,ans=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %d",&a[i],&b[i]);
un[cnt++]=a[i];
un[cnt++]=b[i];
}
sort(un,un+cnt);
cnt=unique(un,un+cnt)-un;//离散化处理
build(1,cnt,1);
for(i=0;i<cnt;i++)
id[un[i]]=i+1;
for(i=n-1;i>=0;i--)//从后往前遍历
{
if(post(id[a[i]],id[b[i]],1))
{
// cout<<id[a[i]]<<" id "<<id[b[i]]<<endl;
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
/*
1
10
20 20
18 18
16 16
14 14
12 12
10 10
8 8
6 6
4 4
2 2
*/