题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4380
2012年第9场多校,1001 。
补上。
其实这个做法当时有想到,只是找不出 O(n^3) 范围内 求V的求法。 所以当时只好放弃~ 。。。
赛后才知道,有其实多校第6场,电科的1004跟这题基本上一样。。。 木有来得及去看,尴尬了。。。
不过电科牛给的 V的求法,其思想有点类似于单调队列,只不过队列只有一个元素。。。
以前没想到这种思想还可以用在几何上(做的几何题目太少,木有遇到过),各种新颖。。。
好吧,写写过了~~ 2Y
写完调试过一阵,原因是while写成if 。
CE过一次,原因是 atan2 的参数是double,而我直接放整型进去(编译器没报错)。。。
PS: 后来做了 电科原题,才发现原来我代码是错的,只不过这题数据太弱了,擦,交了两次不同的错代码上去都能AC。。。
还是电科出题严谨啊,数据、标程、描述等质量都严格把关,佩服~~~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const double pi=3.1415926;
const double eps=0e-6;
struct Point{
int x,y;
}pq[1110];
struct Angle{
double agl;
int id_;
Angle(){};
Angle(Point a,Point b,int i){
agl=atan2((double)b.x-a.x,(double)b.y-a.y);
id_=i;
}
}r[3000];
int pn,qn,pqn,rn;
void input(){
int i;
pqn=pn+qn;
for(i=0;i<pqn;++i)
scanf("%d%d",&pq[i].x,&pq[i].y);
}
int cmp(Angle a,Angle b){
return a.agl<b.agl;
}
int s[103][103];
int v[103][103],v_id[103][103];
void init_(){
int i,j,k,cnt,mark;
for(i=0;i<pn;++i){
rn=0;
for(j=0;j<pqn;j++)
if(i!=j) r[rn++]=Angle(pq[i],pq[j],j);
sort(r,r+rn,cmp);
for(j=0;j<rn;j++){
r[rn+j]=r[j];
r[rn+j].agl+=2*pi;
}
cnt=0;
mark=0;
for(j=k=0;j<rn;j++){
while(r[k].agl-r[j].agl<pi)
if(r[k++].id_>=pn) cnt++;
if(r[j].id_< pn){
s[i][r[j].id_]=cnt;
v[i][r[j].id_]=mark;
v_id[i][r[j].id_]=j;
}
else{
mark++,cnt--;
}
}
}
}
int xmult(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
int get_v(int a,int b,int c){
if(v_id[a][b]>v_id[a][c]) return v[a][b]-v[a][c];
return qn+v[a][b]-v[a][c];
}
int get_sum(int a,int b,int c){
int sum=0;
if(xmult(pq[a],pq[b],pq[c])<0) swap(b,c);
sum+=s[a][b]+s[b][c]+s[c][a];
sum+=get_v(a,b,c)+get_v(b,c,a)+get_v(c,a,b);
return sum;
}
int deal(){
int i,j,k,res=0;
for(i=0;i<pn;i++)
for(j=i+1;j<pn;j++)
for(k=j+1;k<pn;k++)
res+=get_sum(i,j,k)&1;
return res;
}
int main(){
int t=1;
while(~scanf("%d%d",&pn,&qn)){
input();
init_();
printf("Case %d: %d\n",t++,deal());
}
return 0;
}