题意 n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。
求出最后还能看见多少张海报。
如输入 离散化只要记录1 4 2 6 8 10 7 3
排序后为 1 2 3 4 6 7 8 10
1 2 3 4 5 6 7 8
然后输入
1 4
1~4=1 1
2 6
1=1 2~5=2 2
8 10
1=1 2~5=2 7~8=3 3
3 4
1=1 2=2 3~4=4 5=2 7~8=3 4
7 10
1=1 2=2 3~4=4 5=2 6~8=5 4
然后看有几种不同颜色
但是当输入
3
1 8
1 4
6 8
时比较特殊
1 4 6 8
1 2 3 4
1~4=1 1
1~2=2 3~4=1 2
1~2=2 3~4=3 2
而实际上为3
所以
可以 在相差大于一的中间加上一个数
变成 1 3 4 5 6 7 8
就可以了
Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cstdio> #include<string> #include<set> #include<map> #include<queue> #include<vector> #include<stack> using namespace std; #define ll long long #define cl(a,b) memset(a,b,sizeof(a)) #define N 50005 #define MAXN 10005 #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r int sum[MAXN<<4],n,a[MAXN<<3]; int li[MAXN],ri[MAXN]; int f[MAXN]; int ans; /*void push_up(int i)//是把当前结点的信息更新到父结点 { sum[i]=min(sum[i<<1],sum[i<<1|1]); }*/ void push_down(int i)//是把当前结点的信息更新给儿子结点 { sum[i<<1]=sum[i<<1|1]=sum[i]; sum[i]=-1; } /*void build(int L,int R,int i,int l,int r) { sum[i]=r-l+1; if(l==r)return; int mid=(l+r)>>1; build(L,R,lson); build(L,R,rson); }*/ void update(int L,int R,int c,int i,int l,int r) { if(l>=L&&r<=R) { sum[i]=c; return; } if(sum[i]!=-1)push_down(i); int mid=(l+r)>>1; if(L<=mid)update(L,R,c,lson); if(R>mid)update(L,R,c,rson); } void query(int i,int l,int r) { if(sum[i]!=-1) { if(!f[sum[i]]){ f[sum[i]]=1; ans++; } return; } if(l==r)return; int mid=(l+r)>>1; query(lson); query(rson); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); int m=0; cl(sum,-1); cl(f,0); for(int i=1;i<=n;i++) { scanf("%d%d",&li[i],&ri[i]); a[++m]=li[i]; a[++m]=ri[i]; } sort(a+1,a+m+1); int j=1; for(int i=2;i<=m;i++) if(a[i]!=a[i-1])a[++j]=a[i]; for(int i=j;i>=2;i--) if(a[i]-a[i-1]>1)a[++j]=a[i]-1; sort(a+1,a+j+1); for(int i=1;i<=n;i++) { int l=lower_bound(a+1,a+j+2,li[i])-a; int r=lower_bound(a+1,a+j+2,ri[i])-a; update(l,r,i,1,1,j); } ans=0; query(1,1,j); printf("%d\n",ans); } return 0; }