传送门::http://poj.org/problem?id=2528
题意: 在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
数据:1 <= i <= n, 1 <= li <= ri <= 10000000;1 <= n <= 10000
思路:离散化+线段树
离散化 定义::把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。(by百度百科)
通俗点说就是 在不改变数据的可用性质下缩小其范围,一般只关注他们的相对大小
但对于本题而言普通离散化不行,我们还要维护一个性质,那就是是否相邻,举个例子就会明白
[1,5] [1,2] [4,5]离散后[1,4] [1,2][3,4]这样做的答案为2(原因就是二三区间归为一起,导致覆盖第一区间),而实际上答案为3
那我们应该在差值大于1的两个数之间插入一个数,避免相邻的归为一个区间
所以 离散化两性质:大小关系和是否相邻
线段树:
只需开一个数组来标记出现过的颜色即可

1 //#include<bits/stdc++.h>
2 #include<stdio.h>
3 #include<algorithm>
4 #include<string.h>
5 #include<string>
6 #include<iostream>
7 #define ll long long
8 const int maxn=1e5+5;
9 using namespace std;
10
11 int a[maxn],b[maxn],c[maxn*2];
12 int lazy[maxn<<2];
13 bool use[maxn<<2];
14 int ans;
15
16 void pushdown(int rt)
17 {
18 if(lazy[rt]){
19 lazy[2*rt]=lazy[2*rt+1]=lazy[rt];
20 lazy[rt]=0;
21 }
22 }
23 void update(int L,int R,int l,int r,int rt,int add)
24 {
25 if(L<=l&&R>=r){
26 lazy[rt]=add;
27 return ;
28 }
29 int mid=(l+r)>>1;
30 pushdown(rt);
31 if(L<=mid){
32 update(L,R,l,mid,2*rt,add);
33 }
34 if(R>mid){
35 update(L,R,mid+1,r,2*rt+1,add);
36 }
37 }
38 void query(int L,int R ,int l,int r,int rt)
39 {
40 if(lazy[rt]!=0){
41 if(!use[lazy[rt]])ans++;
42 use[lazy[rt]]=1;
43 return ;
44 }
45 if(l==r){return ;}
46 int mid=(l+r)>>1;
47 if(L<=mid){
48 query(L,R,l,mid,2*rt);
49 }
50 if(R>mid){
51 query(L,R,mid+1,r,2*rt+1);
52 }
53 }
54 int main()
55 {
56 int t,k,m;
57 scanf("%d",&t);
58 while(t--){
59 m=ans=0;
60 memset(use,0,sizeof(use));
61 memset(lazy,0,sizeof(lazy));
62 scanf("%d",&k);
63 for(int i=1;i<=k;i++)
64 {
65 scanf("%d%d",&a[i],&b[i]);
66 c[++m]=a[i];c[++m]=b[i];
67 }
68 sort(c+1,c+m+1);
69 m=unique(c+1,c+m+1)-c;
70 m--;
71 for(int i=m;i>1;i--)
72 {
73 if(c[i]-1>c[i-1]){
74 c[++m]=c[i-1]+1;
75 }
76 }
77 sort(c+1,c+m+1);
78 m=unique(c+1,c+m+1)-c;
79 for(int i=1;i<=k;i++){
80 a[i]=lower_bound(c+1,c+m,a[i])-c;
81 b[i]=lower_bound(c+1,c+m,b[i])-c;
82 update(a[i],b[i],1,m-1,1,i);
83 }
84 query(1,m-1,1,m-1,1);
85 cout<<ans<<endl;
86 }
87 return 0;
88 }
