問題蟲洞: TOYS POJ - 2318
黑洞內窺:
多組測試,一行六個數n, m, x1, y1, x2, y2;
鎖定一個矩陣的左端點爲(x1, y1),右下點爲(x2, y2),
緊跟着n行,一行兩個數a,b,代表(a, y1) 到 (b, y2)之間有一條直線。
n個點n條分割線將矩陣分成了n+1個區域。。。
再接着m個點的座標(x, y) ,最後輸出每個區域的點數。
(注意:點不會落在斜線上,且一定在矩陣內)
思維光年:
其實容易想到的是,求出每條分割線的斜率,
然後用m個點的縱座標y去求出每條分割線下對應的x,
由於分割線是從左到右給出的,
所以我們可以遍歷一遍所以的分割線,如果 X > Xm
則該點就在該區域內,時間複雜度爲O(n*m),
坑點:
我一開始是用全cin 讀入,,,上面的複雜度O(n*m),我想也是,理所當然的殘忍TLE,
然後我就二分分割線線斜率, 但還是TLE,這讓我實在費解。。
最後我把所有的cin改成sacnf,,,,二分代碼AC
暴力代碼居然也。。。。綠了~~~~~我懷疑我被scanf綠了。。。
警告!警告!警告!: 請使用scanf! 請使用scanf!請使用scanf!
ACcode:(二分斜率)
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
typedef long long int ll;
const ll MAXN = 5005;
#define INF 0x3f3f3f3f//將近ll類型最大數的一半,而且乘2不會爆ll
const ll mod = 100000007;
const double eps = 0.0000001;
pair<double, double>p[MAXN];
int n, m;
double x1, y1, x2, y2;
int num[MAXN];
double is[MAXN];
int main()
{
while(cin >> n && n)
{
memset(num, 0, sizeof(num));
memset(is, 0, sizeof(is));
scanf("%d %lf %lf %lf %lf", &m, &x1, &y1, &x2, &y2);
for(int i=0; i<n; ++i)
{
double a, b;
scanf("%lf %lf", &a, &b);
if(a == b)
is[i] = a;
else
{
p[i].first = (y1-y2)*1.0/(a-b);
p[i].second = y1*1.0 - p[i].first*a;
}
}
is[n] = x2;
for(int i=0; i<m; ++i)
{
int x, y;
scanf("%d %d", &x, &y);
int l=0, r = n;
while(l <= r)
{
int mid = (l+r)/2;
double ans;
if(is[mid])
ans = is[mid];
else
ans = (y*1.0 - p[mid].second)/ p[mid].first;
if(ans > x)
r = mid-1;
else
l= mid+1;
}
num[l]++;
}
for(int i=0; i<=n; ++i)
cout << i << ": " << num[i] << '\n';
cout << '\n';
}
return 0;
}
ACcode:(改成scanf的暴力AC)
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
typedef long long int ll;
const ll MAXN = 5005;
#define INF 0x3f3f3f3f//將近ll類型最大數的一半,而且乘2不會爆ll
const ll mod = 100000007;
const double eps = 0.0000001;
pair<double, double>p[MAXN];
int n, m;
double x1, y1, x2, y2;
int num[MAXN];
double is[MAXN];
int main()
{
while(cin >> n && n)
{
memset(num, 0, sizeof(num));
memset(is, 0, sizeof(is));
scanf("%d %lf %lf %lf %lf", &m, &x1, &y1, &x2, &y2);
for(int i=0; i<n; ++i)
{
double a, b;
scanf("%lf %lf", &a, &b);
if(a == b)
{
is[i] = a;
}
else
{
p[i].first = (y1-y2)*1.0/(a-b);
p[i].second = y1*1.0 - p[i].first*a;
}
}
is[n] = x2;
for(int i=0; i<m; ++i)
{
double x, y;
scanf("%lf %lf", &x, &y);
for(int j=0; j<=n; ++j) //暴力。。。
{
double ans;
if(is[j])
ans = is[j];
else
ans = (y*1.0 - p[j].second)/ p[j].first;
if(ans >= x)
{
num[j]++;
break;
}
}
}
for(int i=0; i<=n; ++i)
{
cout << i << ": " << num[i] << '\n';
}
cout << '\n';
}
return 0;
}