計算幾何小結

計算幾何小結!

零,說在前面

(轉載請註明原文地址:http://www.cnblogs.com/LadyLex/p/8379553.html )html

此次總結的是計算幾何!ios

根據學長們的觀點,計算幾何是一類0or100的題目算法

可是事實上,計算幾何題目很考驗碼力和細節處理能力,以及數學上平幾和立體幾何那堆東西……ide

我我的以爲這樣的題目是對我的很好的鍛鍊,雖然我考場上仍是隻能打暴力罷了2333工具

那麼咱們開始總結吧!優化

一,凸包

這大概是咱們的萬惡之源了……這裏我把以前的凸包總結搬過來atom

而後續寫兩句如今的理解spa

凸包實際上是一種最優化的體現,它經過把處理的對象從全集減小到一些「更可能成爲最優答案」的點上,從而使咱們能更快獲得答案code

這點尤其體如今DP的斜率優化上htm

固然,凸包也在數學和幾何方面毒瘤着發揮着做用,也有不少巧妙的題目,好比上面那道uoj243破壞導蛋的處理,那個是個人確沒有想到的

固然也有關於凸包的不少算法,可是維護凸包的算法只是工具,重要的仍是凸包體現的最優化思想

我以爲在我作過的凸包的題裏面給我印象最深的就是uoj319分身術了

充分的利用了題目k比較小的條件,維護了子區間的凸包而且合併,從而支持了快速查詢

這是我自從聯賽前打模擬題(殺螞蟻等等)以來打過的最考碼力的一道題,打完以後的確感受碼力獲得提高2333雖然如今仍是鹹魚的打不出來

然而若是考出來仍是隻能打暴力……

二,旋轉卡殼

施工ing……

三,半平面交

這玩意其實和高考數學的線性規劃是一個東西……

之前的總結正在補……

先寫下最近作的題目……

  UOJ#242 破壞蛋糕

    施工ing……

  UOJ#243 破壞導蛋

    題意很簡潔,可是很巧妙也很難想

    我本身能想出加起來總共70pts……

    前20pts暴力不用說啦……

    中間有20pts座標範圍很小,咱們能夠維護每一個x座標y的前綴和,而後對於每次詢問暴力查詢

    這樣的複雜度是$O(n+200^{2}+200m)$的,能夠經過那部分數據

    而後後面有一個不少直線平行的部分分,我以爲能夠對於每種直線,維護每一個點ax+by的值,而後查詢……

    這個東西應該能夠搞個分塊維護下,塊內存個排序,整塊用二分,散點暴力

    這樣加起來是70pts

    後面的我還不會作,正在想……

    咱們仍是慫題解吧,這個太巧妙了

    咱們上面那個維護查詢的問題是每一種ax+by都要處理一次,可是咱們能夠發現對於某兩個點,他們只會在特定的(a,b)處相等

    這樣,不一樣的序列只有$O(n^{2})$級別

    而後咱們考慮分塊跑這個$n^2$,而後維護一個bitset表示合法

    ……操做很辣眼睛,我只能將近看懂jiry的標程

    啊……我把帶註釋的std存在這……

  1 #include <iostream>
  2 #include <cmath>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <cstring>
  6 #include <bitset>
  7 using namespace std;
  8 #define LL long long
  9 
 10 const int size=200;
 11 struct point
 12 {
 13     int x,y;
 14     double getw(int flag=0)
 15     {
 16         if (flag) return atan2(-y,x);
 17         return atan2(y,x);
 18     }
 19     void scan(){scanf("%d%d",&x,&y);}
 20 
 21 }A[51000],B[size+10],f[size+10];
 22 
 23 point operator - (point k1,point k2) {return (point){k1.x-k2.x,k1.y-k2.y};}
 24 int n,N,m,ans[110000],a[size+10],where[size+10],wa,wb;
 25 double w[size+10];
 26 bitset<size+10>an[110010],C[size+10],tot;
 27 struct ask
 28 {
 29     int a,b,where;
 30     LL c;
 31     double w;
 32     void set(point k1,point k2)
 33         {a=k2.y-k1.y,b=-(k2.x-k1.x),c=-((LL)k1.x*a+(LL)k1.y*b),w=atan2(a,b);}
 34 
 35     int pd(point k1){return (LL)k1.x*a+(LL)k1.y*b+c<=0;}
 36 
 37     void rev(){a=-a,b=-b,c=-c,w=atan2(a,b);}
 38 }x[310000];
 39 
 40 int compare(ask k1,ask k2){return k1.w<k2.w;}
 41 
 42 int compare2(int k1,int k2){return w[k1]<w[k2];}
 43 
 44 const double pi=acos(-1);
 45 
 46 int compare3(int k1,int k2)//comp ax+by
 47     {return (LL)B[k1].x*wa+(LL)B[k1].y*wb<(LL)B[k2].x*wa+(LL)B[k2].y*wb;}
 48 
 49 struct atom{int u,v;double w;}y[110000];
 50 
 51 int len;
 52 
 53 LL k1xk2(point k1,point k2){return (LL)k1.x*k2.y-(LL)k1.y*k2.x;}
 54 
 55 int compare4(const atom &k1,const atom &k2){return k1.w<k2.w;}
 56 
 57 int check(atom k1,atom k2)//兩向量平行
 58 {
 59     point a=B[k1.v]-B[k1.u],b=B[k2.v]-B[k2.u];
 60     return k1xk2(a,b)==0&&(LL)a.x*b.x>=0&&(LL)a.y*b.y>=0;
 61 }
 62 
 63 int check(point k1,point k2)//至關於上面的comp3,比較了ax+by
 64     {return (LL)k1.x*wa+(LL)k1.y*wb<(LL)k2.x*wa+(LL)k2.y*wb;}
 65 
 66 void gopre(int k)//因爲a和b的更改帶來的順序更改
 67 {
 68     while ( where[k]>1 &&check( B[k],B[ a[where[k]-1] ]  ))
 69     {
 70         int k1=where[k],k2=a[k1-1];
 71         swap(a[k1],a[k1-1]);
 72         swap(f[k1],f[k1-1]);
 73         C[k1-1][k]=1; C[k1-1][k2]=0;
 74         where[k]--; where[k2]++;
 75     }
 76 }
 77 void getw(int k1)
 78 {
 79     int l=1,r=n+1,ans=n+1;
 80     LL aa=x[k1].a,b=x[k1].b,c=x[k1].c;
 81     while (l<r)
 82     {
 83         int mid=(l+r)>>1;
 84         if(aa*f[mid].x+b*f[mid].y+c<=0)l=mid+1;
 85         else ans=mid,r=mid;
 86     }
 87     an[x[k1].id]&=C[ans-1]; 
 88 }
 89 
 90 
 91 int sign,pd[size+10],s[size+10],head;
 92 void insert(int k1)
 93 {
 94     if (pd[k1]!=sign)
 95         pd[k1]=sign,s[++head]=k1;
 96 }
 97 
 98 
 99 void solve(){
100     memset(an,0x00,sizeof an);
101 
102     tot=0; 
103     for(int i=1;i<=n;i++)tot[i]=1;
104     for (int i=1;i<=m/3;i++)an[i]=tot;
105     wa=0; wb=-1;
106 
107     for (int i=1;i<=n;i++)a[i]=i;
108     sort(a+1,a+n+1,compare3);//comp ax+by
109     for (int i=1;i<=n;i++)//記錄每一個點如今的排名,而後f是排序後的結果
110         where[a[i]]=i,f[i]=B[a[i]];
111     for (int i=1;i<=n;i++)//C是點集前綴和
112         C[i]=C[i-1],C[i][a[i]]=1;
113     
114     len=0;
115     for(int i=1;i<=n;i++)
116         for(int j=1;j<=n;j++)
117             if(i^j)//由j指向i的向量,包括id以及……極角?這個極角是什麼操做?
118                 //這大概就是題解中所說的關鍵點吧……
119                 //若是按照我昨天推的轉化式子這玩意是對的,a等於-y,b等於x
120             {
121                 y[++len]=(atom){  j,i,(B[i]-B[j]).getw(1)  };
122                 if(B[i].y==B[j].y)
123                 {
124                     if(B[j].x>B[i].x)y[len].w=-pi;
125                     else y[len].w=0;
126                 }
127             }
128     sort(y+1,y+len+1,compare4);//按極角排序?
129     int pre=1,now=1; y[len+1].w=pi;
130     for (int i=1;i<=len+1;i++)
131     {
132         while(now<=m&&x[now].w<=y[i].w)getw(now++);
133         //還沒達到下一個關鍵點,如今能夠更新答案
134         if ( ( i!=len+1  &&  check(y[i],y[i+1])==0    )  || i==len )
135         {//到達關鍵點(與下一個不平行)
136             wa=-(B[y[i].v].y-B[y[i].u].y);
137             wb=B[y[i].v].x-B[y[i].u].x;
138             //
139             point pre1=(point){wa,wb};
140             if(i==len)wb--;//進行一些偏移
141 
142             else 
143                 wa-=B[y[i+1].v].y-B[y[i+1].u].y,
144                 wb+=B[y[i+1].v].x-B[y[i+1].u].x;
145             if(k1xk2(pre1,(point){wa,wb})==0)//共線?剛纔不是判了麼?
146                 wa=pre1.y,wb=-pre1.x;
147 
148             head=0;sign++; 
149             for (int j=pre;j<=i;j++)
150                 insert(where[y[j].u]),insert(where[y[j].v]);
151             //插入這段時間內新的點
152             sort(s+1,s+head+1);
153             for (int j=1;j<=head;j++)//進行交換
154                 gopre(a[s[j]]);
155             pre=i+1;
156         }
157     }
158     for (int i=1;i<=m/3;i++) ans[i]+=an[i].count();
159 }
160 int main(){
161 
162 
163 
164     scanf("%d%d",&N,&m); 
165     for (int i=1;i<=N;i++) A[i].scan();
166     for (int i=1;i<=m;i++){
167         point k1,k2,k3; k1.scan(); k2.scan(); k3.scan();
168         x[i*3-2].set(k1,k2);
169         x[i*3-1].set(k2,k3);
170         x[i*3].set(k3,k1);
171         if (x[i*3-2].pd(k3)==0) x[i*3-2].rev();
172         if (x[i*3-1].pd(k1)==0) x[i*3-1].rev();
173         if (x[i*3].pd(k2)==0) x[i*3].rev();
174     }
175 
176 
177 
178     m*=3;
179     for (int i=1;i<=m;i++) x[i].id=(i-1)/3+1;
180     sort(x+1,x+m+1,compare);
181     for (int l=1;l<=N;l+=size)
182     {
183         int r=min(N,l+size-1);
184         n=r-l+1;
185         for(int i=l;i<=r;i++)
186             B[i-l+1]=A[i];
187         solve();
188     }
189     m/=3;
190     for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
191     return 0;
192 }
UOJ#243std

    

四,Simpson積分

施工ing……

五,沒作兩道題的其餘專題

  一,平面圖轉對偶圖

    施工ing……

  二,隨機化算法

    1.最小圓覆蓋

    施工ing……

  三,三維幾何

    施工ing……

六,總結

施工ing……

相關文章
相關標籤/搜索