线段树 区间修改+离散化处理
#include<iostream>
#include<algorithm>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<cctype>
#include<vector>
#include<limits.h>
#include<queue>
#include<stack>
using namespace std;
int n;
struct si
{
int l,r;
};
si s[10100];
int x[20200]; //存放所有海报的端点瓷砖编号
int hash1[20200]; //hash[i]表示瓷砖i所处的离散化后的区间编号
struct mmp
{
int L,R;
bool bCovered; //区间[L,R]是否已经被完全覆盖
mmp * pLeft, * pRight;
};
mmp Tree[202000];
int nNodeCount = 0;
int Mid( mmp * pRoot)
{
return (pRoot->L + pRoot->R)/2;
}
void BuildTree(mmp *pRoot,int L,int R)
{
pRoot->L = L;
pRoot->R = R;
pRoot->bCovered = false;
if( L == R )
return;
nNodeCount ++;
pRoot->pLeft = Tree + nNodeCount;
nNodeCount ++;
pRoot->pRight = Tree + nNodeCount;
BuildTree( pRoot->pLeft,L,(L+R)/2);
BuildTree( pRoot->pRight,(L+R)/2 + 1,R);
}
bool Post(mmp *pRoot, int L, int R)
{
//插入一张正好覆盖区间[L,R]的海报,返回true则说明区间[L,R]是部分或全部可见的
if( pRoot->bCovered )
return false;
if( pRoot->L == L && pRoot->R == R)
{
pRoot->bCovered = true;
return true;
}
bool bResult ;
if( R <= Mid(pRoot) )
bResult = Post( pRoot->pLeft,L,R);
else if( L >= Mid(pRoot) + 1)
bResult = Post( pRoot->pRight,L,R);
else
{
bool b1 = Post(pRoot->pLeft,L,Mid(pRoot));
bool b2 = Post( pRoot->pRight,Mid(pRoot) + 1,R);
bResult = b1 || b2;
}
//要更新根节点的覆盖情况
if( pRoot->pLeft->bCovered && pRoot->pRight->bCovered )
pRoot->bCovered = true;
return bResult;
}
int main()
{
int t,i,a;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int m=0;
for(i=0; i<n; i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
x[m++]=s[i].l;
x[m++]=s[i].r;
}
sort(x,x+m);
m = unique(x,x+m) - x; //去掉重复元素 //下面离散化
a=m;
for(i=1; i<a; ++i)
{
if(x[i]-x[i-1]>1)
{
x[m++]=x[i-1]+1;
}
}
sort(x,x+m);
BuildTree(Tree,0,m);
int nSum=0;
for(i=n-1; i>=0; i--) // 从后往前看每个海报是否可
{
int c=lower_bound(x,x+m,s[i].l)-x;
int d=lower_bound(x,x+m,s[i].r)-x;
if(Post(Tree,c,d))
nSum ++;
}
printf("%d\n",nSum);
}
return 0;
}