題目意思是在一道牆上貼海報,後面貼的海報可能把前面的覆蓋,之後給出一個區間,要輸出這個區間內能夠看見的海報數目。
乍一看非常像POJ 2777塗顏料那道題目,仔細一想還是有很大的不同。首先海報數量十分巨大,不可能用上位運算,這也意味着每次query都要查詢到線段樹的葉。其次牆所表示的區間十分大,即時能夠被 __int64 表示,過大的區間也很容易造成MLE。所以要用上離散化,將整個區間縮小到相對極小的範圍內(其實不知道爲啥這叫離散化。。)。
最後的代碼AC了,但其實還是有問題,離散化的時候沒有處理好,導致區間之間的間隙變成了0。可是還是過了,可能是數據太弱。另外也用了lazy,不過可能即使不用也能過。
#include<cstdio>
#include<set>
#include<algorithm>
#include<iostream>
#define MID(x, y) (x + y >> 1)
#define L(x) (x) << 1
#define R(x) (x) << 1 | 1
using namespace std;
typedef struct{
int l, r;
int post;
int offset;
} NODE;
typedef struct {
int val;
int id;
bool isLeft;
} MAP;
MAP input[40000];
NODE st[88000];
int Left[20000], Right[20000];
set<int> result;
void build(long long t, int l, int r){
st[t].l = l;
st[t].r = r;
st[t].post = 0;
st[t].offset = 0;
if(l == r)
return;
else{
build(L(t), l, MID(l, r));
build(R(t), MID(l, r) + 1, r);
}
}
void update(long long t, int l, int r, int p){
if(st[t].l == l && st[t].r == r){
st[t].post = p;
st[t].offset = p;
return;
}
if(st[t].offset && st[t].l != st[t].r){
st[L(t)].post = st[t].offset;
st[R(t)].post = st[t].offset;
st[L(t)].offset = st[t].offset;
st[R(t)].offset = st[t].offset;
st[t].offset = 0;
}
st[t].post = -1;
int mid = MID(st[t].l, st[t].r);
if(mid >= r){
update(L(t), l, r, p);
}else if(mid < l){
update(R(t), l, r, p);
}else{
update(L(t), l, mid, p);
update(R(t), mid + 1, r, p);
}
}
void query(int t, int l, int r){
if(st[t].l == l && st[t].r == r && st[t].post != -1){
result.insert(st[t].post);
return;
}
if(st[t].offset){
st[L(t)].post = st[t].offset;
st[R(t)].post = st[t].offset;
st[L(t)].offset = st[t].offset;
st[R(t)].offset = st[t].offset;
st[t].offset = 0;
}
st[t].post = -1;
int mid = MID(st[t].l, st[t].r);
if(mid >= r){
query(L(t), l, r);
}else if(mid < l){
query(R(t), l, r);
}else{
query(L(t), l, mid);
query(R(t), mid + 1, r);
}
}
bool cmp(MAP a, MAP b){
return a.val < b.val;
}
int main(){
int N;
scanf("%d", &N);
while(N--){
int O;
scanf("%d", &O);
for(int i = 1; i <= O; i++){
int x, y;
scanf("%d %d", &input[i * 2 - 1].val, &input[i * 2].val);
input[i * 2 - 1].id = i;
input[i * 2 - 1].isLeft = true;
input[i * 2].id = i;
input[i * 2].isLeft = false;
}
sort(input + 1, input + 2 * O + 1, cmp);
int value = input[1].val;
int t = 1;
for(int i = 1; i <= 2 * O; i++){
if(value != input[i].val){
value = input[i].val;
t++;
}
// cout << input[i].id << " " << input[i].val << " " << t << endl;
if(input[i].isLeft){
Left[input[i].id] = t;
}else{
Right[input[i].id] = t;
}
}
// for(int i = 1; i <= O; i++){
// cout << Left[i] <<" " << Right[i] << endl;
// }
build(1, 1, 20000);
for(int i = 1; i <= O; i++){
// cout << Left[i] << Right[i]<<endl;;
update(1, Left[i], Right[i], i);
}
result.clear();
query(1, 1, 20000);
result.insert(0);
result.insert(-1);
cout << result.size() - 2 << endl;
}
}