问题虫洞: 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;
}