题目大意:给定一块长度为 L 的木板,宽度为 1,将其按长度分成 L 个单元格,编号为 1 到 L。
现在往木板上贴 N 张 posters,长度为Li ,每贴一张给(i,j)表示从 i 号 到 j 号被贴(木板被覆盖)。后贴的将前面的覆盖。到最后一张贴完,每张poster只要有一部分露出来就视为该 poster 可见,求贴完 N 张后一共有多少张是可见的。
1 <= N <= 10000 , 1<=L,Li<=
10000000
Sample Input
1
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
解题思路:线段树+离散化
#include <iostream>
#include <cstdio>
#include <cstring>
#define Max 10005
using namespace std;
struct Node{int v; int num;}node[Max<<2];
intcover[Max<<4];
bool cmp1(Node a,Node b)
{if(a.v<=b.v) return true;
return false;
}
bool cmp2(Node a,Node b)
{if(a.num>b.num) return true;
if(a.num==b.num&&a.v<b.v) return true;
return false;
}
void build(int l,int r,int id)
{if(l==r) { cover[id]==0; return; }
int m=(l+r)/2;
build(l,m,id*2); build(m+1,r,id*2+1);
}
int haha;//用来标记每次query后的结果,-1为不能贴,1表示能
void PushUp(int id)
{if(cover[id*2]==2&&cover[id*2+1]==2) cover[id]=2; }
void query(int L,int R,int l,int r,int id)
{if(L<=l&&R>=r)
{ if(cover[id]!=2)
{ haha=1; cover[id]=2; return; }
return;
}
if(cover[id]==2) return;
cover[id]=1;
int mid=(l+r)/2;
if(R<=mid) query(L,R,l,mid,id*2);
else if(L>mid) query(L,R,mid+1,r,id*2+1);
else{query(L,mid,l,mid,id*2); query(mid+1,R,mid+1,r,id*2+1);} PushUp(id);
}
int main()
{//freopen("in.txt","r",stdin);
int test,n,i;
scanf("%d",&test);
while(test--)
{ memset(cover,0,sizeof(cover)); scanf("%d",&n);
for(i=0;i<n;i++)
{ scanf("%d%d",&node[i*2].v,&node[i*2+1].v); node[i*2].num=node[i*2+1].num=i+1;
}
sort(node,node+2*n,cmp1);
//离散化
int k=1,pre=0;
for(i=0;i<n*2;i++)
{ if(pre!=node[i].v)
{ if(node[i].v-pre>1) { pre=node[i].v; k+=2; node[i].v=k; }
else { pre=node[i].v; k++; node[i].v=k; }
}
else
node[i].v=k;
} //k = 新的节点数
build(1,k,1);
sort(node,node+2*n,cmp2);
int ans=0;
for(i=0;i<n;i++)
{ haha = -1;
query(node[i*2].v,node[i*2+1].v,1,k,1);
if(haha==-1) continue;
ans++;
}
printf("%d\n",ans);
}
return 0;
}