叉積+二分
如果toys在當前板的左邊 cross(L,toys,U) < 0
反之在右邊會 > 0
根據這個,我們進行二分;
為什麼最後得到的不是mid而是l呢?
我們來看這張圖.
加入現在是 l = 2 , r = 5;mid = 3; toy在4紙板右邊,5紙板左邊,
執行l = l +1 = 3, r = 5, mid = 4;依然>0 執行,
l = l + 1 = 4,r = 5, mid = 4; 依然大於0 ,執行
l = l + 1 = 5, r= 5, 退出; 此時l = 5, 之前toy確實在l右邊,可是現在在它左邊了.(有的情況還是會在右邊)
所以我們後面要加一個判斷:
if(cross(CardB[r].L, Toys, CardB[r].U) < 0) N_Toys[l]++;else N_Toys[l+1]++;
顯然,我們同樣可以:
if(cross(CardB[r].L, Toys, CardB[r].U) > 0) N_Toys[r+1]++;else N_Toys[r]++;
那麼,如果利用mid 改怎麼改寫代碼呢?
for(int i = 0; i < m; i++) { l = 0, r = n-1; scanf("%d%d",&Toys.x,&Toys.y); while(l <= r) { mid = (l + r) >> 1; if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0) l = mid + 1; else r = mid - 1; } if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0) N_Toys[mid+1]++; else N_Toys[mid]++; }
/* *POJ 2318 *fuqiang *幾何初步 *2013/8/2*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>using namespace std;const int maxn = 5000+3;const double PI = 4.0*atan(1.0);const double eps = 1e-8;struct point{ int x; int y;} Toys;struct Line{ point U; point L;} CardB[maxn];int N_Toys[maxn];int cross(const point &p0, const point &p1, const point &p2) //計算叉積{ return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);}int main(){#ifndef ONLINE_JUDGE freopen("in","r",stdin);#endif int n,m,x1,y1,x2,y2; while(scanf("%d",&n) && n) { scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); for(int i = 0; i < n; i++) { scanf("%d%d", &CardB[i].U.x, &CardB[i].L.x); CardB[i].U.y = y1; CardB[i].L.y = y2; } memset(N_Toys,0,sizeof(N_Toys)); int l, r, mid, ans, p; for(int i = 0; i < m; i++) { l = 0, r = n-1; scanf("%d%d",&Toys.x,&Toys.y); while(l < r) { mid = (l + r) >> 1; if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0) l = mid + 1; else r = mid; } if(cross(CardB[r].L, Toys, CardB[r].U) < 0) N_Toys[l]++; else N_Toys[l+1]++; } for(int i = 0; i <= n; i++) { printf("%d: %d\n",i,N_Toys[i]); } printf("\n"); }}
還有個更好的點子,別人的代碼:
將最後一個點也作為紙板,此時 我們只需要返回l:
while (l <= r){ mid = (l + r) >> 1; if ( cal (low[mid], high[mid], cc) > 0 ) l = mid + 1; else r = mid - 1; } return l;}
POJ 2398
加個排序,統計後輸出,注意t>0
/* *POJ 2318 *fuqiang *幾何初步 *2013/8/2*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>using namespace std;const int maxn = 5000+3;const double PI = 4.0*atan(1.0);const double eps = 1e-8;struct point{ int x; int y;} Toys;struct Line{ point U; point L;} CardB[maxn];int N_Toys[maxn];int cross(const point &p0, const point &p1, const point &p2) //計算叉積{ return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);}int cmp(Line a, Line b)//sort...{ return a.L.x < b.L.x;}int main(){#ifndef ONLINE_JUDGE freopen("in","r",stdin);#endif int n,m,x1,y1,x2,y2; while(scanf("%d",&n) && n) { scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); for(int i = 0; i < n; i++) { scanf("%d%d", &CardB[i].U.x, &CardB[i].L.x); CardB[i].U.y = y1; CardB[i].L.y = y2; } sort(CardB,CardB+n,cmp); //sort memset(N_Toys,0,sizeof(N_Toys)); int l, r, mid, ans, p; for(int i = 0; i < m; i++) { l = 0, r = n-1; scanf("%d%d",&Toys.x,&Toys.y); while(l <= r) { mid = (l + r) >> 1; if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0) l = mid + 1; else r = mid - 1; } if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0) N_Toys[mid+1]++; else N_Toys[mid]++; } sort(N_Toys,N_Toys+n+1); printf("Box\n"); int st = 0; while(N_Toys[st] == 0) st++; for(int i = st; i <= n; ) { int num = 1; printf("%d: ",N_Toys[i]); for(int j = i++; j <= n; j++,i++) { if(N_Toys[i]==N_Toys[j]) num++; else break; } printf("%d\n",num); }// printf("\n"); }}