原題鏈接:POJ2528
解析:這題考察的是線段樹子區間更新的維護中的計算可見線段。
用離散化,排序去重,但是這題廣告是一塊瓷磚一塊瓷磚貼的,也就是說有可能離散化之後,明明倆個相鄰點之前有空白,但是由於離散化分配序號是緊挨着的,就造成了倆塊有廣告瓷磚緊挨。舉個例子,比如四號瓷磚(以下用號簡稱)和五號都有廣告,那麼離散化之後四號序號爲1,五號爲2,他們之間沒別的位置,故全覆蓋,那如果四號和六號有廣告,但是五號沒有,由於我們離散化記錄的是廣告左右邊,故四號爲1,六號爲2,那麼他們之間還是沒空白,這就與題意不符了。所以當相鄰邊大於1時,序號要多+1。
代碼實例:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10100;
int x[4*maxn];
int id[10000010];
struct CPost{
int l,r;
bool vis;
}poster[maxn];
struct CNode{
int l,r;
bool bCovered;
int Mid(){
return (l+r)/2;
}
}tree[1000000];
void BuildTree(int root,int l,int r){
tree[root].l = l;
tree[root].r = r;
tree[root].bCovered = false;
if(l == r) return;
BuildTree(2*root+1,l,(l+r)/2);
BuildTree(2*root+2,(l+r)/2+1,r);
}
bool Push(int root,int s,int e){
if(tree[root].bCovered) return false;
if(s == tree[root].l && e == tree[root].r){
tree[root].bCovered = true;
return true;
}
bool res;
if(e <= tree[root].Mid()) res = Push(2*root+1,s,e);
else if(s > tree[root].Mid()) res = Push(2*root+2,s,e);
else{
bool r1 = Push(2*root+1,s,tree[root].Mid());
bool r2 = Push(2*root+2,tree[root].Mid()+1,e);
res = r1 || r2;
}
if(tree[2*root+1].bCovered && tree[2*root+2].bCovered)
tree[root].bCovered = true;
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,cnt;
scanf("%d",&n);
for(int i = 0;i < n;i++){
scanf("%d%d",&x[i],&x[i+n]);
poster[i].l = x[i];
poster[i].r = x[i+n];
}
sort(x,x+2*n);
cnt = unique(x,x+2*n)-x;
int interval = 1;
for(int i = 0;i < cnt;i++){
id[x[i]] = interval;
if(i < cnt-1){
if(x[i+1] - x[i] == 1) interval++;
else interval += 2;
}
}
BuildTree(0,1,interval);
int ans = 0;
for(int i = n-1;i >= 0;i--){
int s = id[poster[i].l];
int e = id[poster[i].r];
if(Push(0,s,e)) ans++;
}
printf("%d\n",ans);
}
return 0;
}