天天看點

求n個矩形面積——坐标離散化

最開始接觸離散的時候是在實驗室第一次暑期集訓的時候,好像是wuyuqi大佬講的,但是當時根本就沒聽懂這是個什麼東西,感覺聽名字這麼高大上,有點難了解。是以當時就沒花時間去研究。

這兩天在補題的時候遇到了這個問題,就看了一些大佬的解釋,算是有一丢丢了解了

求n個矩形面積——坐标離散化

坐标離散我個人的了解就是把一個坐标平面上的有用的點儲存,沒有關系的點壓縮(因為沒有用的點對實際結果根本沒有任何影響)

就以voj的1056題來做一個示範:

求n個矩形面積——坐标離散化

         這題按照最平常的想法就是把矩形内的标記,然後整個圖搜尋,就可以得出共覆寫了多少範圍。但是範圍是-10^8~10^8,這麼搜顯然不可能。是以要怎麼樣呢?

就是把有用的點儲存,無關的點壓縮。什麼是有用的點儲存,什麼是無關的點壓縮?給出的坐标就是有用的點,-10^8~10^8内的範圍内除了給出的坐标範圍其他全是沒用的點,都要壓縮。

有用的值其實隻有這麼幾個。這些值将作為新的坐标值重新劃分整個平面,省去中間的若幹坐标值沒有影響。我們可以将坐标範圍“離散化”到1到200 

之間的數,于是一個200*200的二維數組就足夠了。

現在用個小例子來模拟一下:

注意左邊的10* 7的數組是如何等價地轉化為右邊兩個4*4的數組的 

求n個矩形面積——坐标離散化

再就是代碼實作了:

求n個矩形面積——坐标離散化

如上資料示例   x[ ]={ 1, 3, 7, 10 };

                           y[ ]={ 1,  2,  5,  7 };

按代碼枚舉的順序是如上圖,先看(1,1)點, if(x[i]>=x1[k]&&y[j]>=y1[k]&&x[i+1]<=x2[k]&&y[j+1]<=y2[k])判斷是否是矩形内的然後按順序枚舉,發現(1,1)點不是,再看(1,2)點,s=s(x+1,y+1)-s(x,y)即框2,符合在矩形内,ans+=s,枚舉完了,就得出結果了

include<cstdio>
include<cstdlib>
include<algorithm>
include<iostream>
define MAXn 100
using namespace std;
int n;
long long x1[MAXn+1],y1[MAXn+1];
long long x2[MAXn+1],y2[MAXn+1];
long long x[2MAXn+1],y[2MAXn+1];
long long S,ans;
int main()
{
    scanf("%d",&n); 
    for(int i=1;i<=n;i++) 
    { 
        scanf("%I64d%I64d%I64d%I64d",&x1[i],&y1[i],&x2[i],&y2[i]); 
        x[2i-1]=x1[i]; 
        x[2i]=x2[i]; 
        y[2i-1]=y1[i];
        y[2i]=y2[i]; 
    } 
    sort(x+1,x+2n+1); 
    sort(y+1,y+2n+1); 
    for(int i=1;i<=2n-1;i++) //枚舉每一個機關橫坐标,這兩句看圖 
        for(int j=1;j<=2n-1;j++)  //枚舉每一個機關縱坐标
        { 
            S=(x[i+1]-x[i])*(y[j+1]-y[j]);
            for(int k=1;k<=n;k++) //枚舉每一個矩形塊 
                if(x[i]>=x1[k]&&y[j]>=y1[k]&&x[i+1]<=x2[k]&&y[j+1]<=y2[k])//這句是離散化
                { ans+=S; break; }//注意這個break,用的妙
        } 
    printf("%I64d",ans); return 0; 
}
           

繼續閱讀