最近在做计算机几何的题目,看了北大的分类,把这道题目归到了凸包里面,想不通。。。
这道题目的重点是原来自己阵营的人肯定不会相交,利用这个点,我们可以先输入其中一个阵营,然后在输入第二阵营的过程中,逐个计算相交个数。。。
输入第一阵营后,建立相应对应的区域,然后利用上下界的差来计算出答案。。。
ps:在找第二阵营中的个数在第一阵营的相应位置时,可以用二分查找加快速度,这个读者可以自己去试试。。
#include <iostream>
#include <memory.h>
#include <cstring>
using namespace std;
const long INVALID = -1;
long shoot[60030]; // 记录对应位置的人投射的位置
long cal[60030];
// 返回下一个不同颜色的人投射的位置
long getUpperBound( long now , long max ){
long result = INVALID;
for( long i = now; i <= max; ++i ) {
if( shoot[i] != INVALID ) {
result = shoot[i];
break;
}
}
return result;
}
// 返回上一个不同原色的人投射的位置
long getlowerBound( long now ) {
long result = INVALID;
for( long i = now; i > 0; --i ) {
if( shoot[i] != INVALID ) {
result = shoot[i];
break;
}
}
return result;
}
int main()
{
long t, n, m, i, j, post, target, lower, upper;
long long result;
cin >> t;
for( int k = 1; k <= t; ++k ) {
cin >> n >> m;
memset( shoot, INVALID, sizeof(shoot));
memset( cal, 0, sizeof(cal) );
result = 0;
for( i = 0; i < n; ++i ){
cin >> post >> target;
cal[target] = 1;
shoot[post] = target;
}
for( i = 1, j = cal[0]; i <= n + m + 2; ++i ){
cal[i] = j = j + cal[i];
}
for( i = 0; i < m; ++i ){
cin >> post >> target;
lower = getlowerBound( post );
if( lower >= target ){
result += cal[lower] - cal[target - 1 ];
continue;
}
upper = getUpperBound( post, n + m );
if( upper != INVALID && target >= upper ){
result += cal[target] - cal[upper-1];
}
}
cout << "Scenario #" << k << ":\n";
cout << result << endl;
if( k != t ){
cout << endl;
}
}
}