題目描述:
幾張海報有不同的覆蓋範圍,按先後順序鋪蓋上去,看最終在頂層能看到多少張不同的海報。
解題思路:
線段樹——還是建樹+修改+查詢的基本操作。不過費了一天啊。。。有幾個需要注意的地方,會容易出現MLE,RE或者TLE的。
首先是線段樹標記問題,只標記完全覆蓋的區間的tab,其餘置空以便最後search求出值,目前自己用過的企另外一種標記方式會TLE;然後就是最重要的離散化問題,一開始沒有離散化,用3*M的樹大小都RE,需要開到4*M,但是開到那個地步又會MLE。而現在算一算,其實只開一個M大小的樹就已經超過65535K了。所以必須要進行離散化,即其實這裏面有些區間段完全可以用一個單位區間段來表示,即需要對輸入的數排序去重後,把區間縮減。這樣的話,我們看到總共就輸入10000個線段,最多20000個區間段,這樣的線段樹規模比原先的一千萬就小了很多。
代碼:
#include
#include
typedef struct {
int l,r;
int tab;
}CH;
CH segTree[70000];
int n, num, flag[20001], tmp_array[20002], array[20002], len,
cnt;
int partition(int low, int high){
int tmp =
tmp_array[low];
while(low
while(low < high && tmp_array[high] > tmp)
high --;
if(low
tmp_array[low++] = tmp_array[high];
while(low < high && tmp_array[low] < tmp)
low ++;
if(low < high)
tmp_array[high--] = tmp_array[low];
}
tmp_array[low] = tmp;
return low;
}
void quick_sort(int low, int high){
int
index;
if(low
index = partition(low, high);
quick_sort(low, index-1);
quick_sort(index+1, high);
}
}
int binaryInsert(int low, int high, int t){ //insert t in array, if
not exist then insert, otherwise do not handle. all return the t
pos.
int mid = (low+high)/2;
while(low <= high){
if(t == array[mid]){
return mid;
}else if(t < array[mid]){
high = mid - 1;
}else{
low = mid + 1;
}
mid = (low+high)/2;
}
return low;
}
void buildTree(int l, int r, int index){
segTree[index].l = l;
segTree[index].r = r;
segTree[index].tab = 0;
if(l!=r){
buildTree(l,(l+r)/2,2*index);
buildTree((l+r)/2+1,r,2*index+1);
}
}
void changeTree(int l, int r, int index){
if(segTree[index].l == l
&& r == segTree[index].r){ //恰巧覆蓋,則置爲頂層標號
segTree[index].tab = num;
//printf("改(%d -> %d)範圍值爲 %d.\n",l, r, num);
}else{
if(segTree[index].tab != 0){
segTree[2*index].tab = segTree[index].tab;
segTree[2*index+1].tab = segTree[index].tab;
segTree[index].tab = 0;
}
if( l > (segTree[index].l+segTree[index].r)/2 ){ //右區域
// printf("(%d->%d)在右區域\n",l, r);
changeTree(l,r,2*index+1);
}else if( r <= (segTree[index].l+segTree[index].r)/2 ){
//左區域
// printf("(%d->%d)在左區域\n",l, r);
changeTree(l,r,2*index);
}else{ //橫跨兩個區域
// printf("(%d->%d)跨兩個區域\n",l, r);
changeTree(l,(segTree[index].l+segTree[index].r)/2,2*index);
changeTree((segTree[index].l+segTree[index].r)/2+1,r,2*index+1);
}
}
}
void searchTree(int index){
if(segTree[index].tab !=
0){
if(flag[segTree[index].tab] != 1){
flag[segTree[index].tab] = 1;
cnt ++;
}
}else{
searchTree(2*index);
searchTree(2*index+1);
}
}
main(){
int i, j, max, x[10001],
y[10001], pos;
int test;
scanf("%d",&test);
while(test > 0){
test --;
scanf("%d",&n);
j=1;
for(i=1;i<=n;i++){
scanf("%d %d",&x[i], &y[i]);
tmp_array[j++] = x[i];
tmp_array[j++] = y[i];
}
memset(array,0,sizeof(array));
//做快排後去重
quick_sort(1,2*n); // for tmp_array
array[1] = tmp_array[1];
len = 1;
for(i=2;i<=2*n;i++){// redupliction removing
if(tmp_array[i]!=tmp_array[i-1])
array[++len] = tmp_array[i];
}
//更新值——即所謂的“離散化”
max = 0;
for(i=1;i<=n;i++){
x[i] = binaryInsert(1,len,x[i]);
y[i] = binaryInsert(1,len,y[i]);
if(y[i] > max)
max = y[i];
}
for(i=1;i<=3*max;i++) //清空
segTree[i].tab = 0;