2019CCPC秦皇岛站 A.Angle Beats(hdu 6731)(极角排序)

链接

        Angle Beats

题意

        平面上给2000个固有点,点坐标范围-1e9~+1e9,给2000个询问,每个询问给个点A,问和给定的2000个固有点能组成多少个直角三角形?

思路

        对于给定点A,如果点A当作直角顶点,直接极角排序,对每个固有点判断旋转90°的位置有多少点,累加即可。

        如果A不是直角顶点,应以固有的2000个点为原点,对其他1999个固有点和A极角排序,当扫到A时判断垂直方向有多少个固有点。

        但是对于每次询问都会有O(n*(nlogn+n))的复杂度,在2000个询问的情况下无疑会TLE。

        所以需要以2000个固有点每一个为原点,对剩余点极角排序,遇到询问点时进行处理。可以消除2000个询问带来的影响。

代码

#include 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
static const int maxn = 4010;
static const int INF = 0x3f3f3f3f;
static const int mod = (int)1e9 + 7;
static const double eps = 1e-6;
static const double pi = acos(-1);

void redirect(){
    #ifdef LOCAL
        freopen("test.txt","r",stdin);
    #endif
}

inline int sign(const int& x){return x>0?1:(x==0?0:-1);}

struct point{
    int id,x,y;
    point(int x,int y){
        this->x = x,this->y = y;
    }
    point(){}
}p[maxn],q[maxn],o;

point operator-(const point& a,const point& b){
    return point(a.x-b.x,a.y-b.y);
}

bool operator^ (const point& a,const point& b){
    return (1ll*a.x*b.y - 1ll*a.y*b.x) > 0;
}

inline int Quadrant(const point& a){
    if(a.x>0 && a.y>=0)return 1;
    else if(a.x<=0 && a.y>0)return 2;
    else if(a.x<0 && a.y<=0)return 3;
    else if(a.x>=0 && a.y<0)return 4;
}

bool operator< (const point& c,const point& d){
    point a = c-o,b = d-o;
    int qa = Quadrant(a),qb = Quadrant(b);
    if(qa != qb)return qa < qb;
    return a ^ b;
}

int ans[maxn];

int main(){
    redirect();
    int n,m,ma;
    while(~scanf("%d %d",&n,&m)){
        ma = n+m;
        memset(ans,0,sizeof(ans));
        memset(p,0,sizeof(p));
        for(int i = 1;i <= n;i++){
            p[i].id = i;
            scanf("%d %d",&p[i].x,&p[i].y);
            q[i] = p[i];
        }
        for(int i = n+1;i <= ma;i++){
            p[i].id = i;
            scanf("%d %d",&p[i].x,&p[i].y);
            o = p[i];
            sort(p+1,p+1+n);
            for(int j = 1;j <= n;j++){
                int x = p[j].x - o.x,y = p[j].y - o.y;
                point a = point(o.x-y,o.y+x);
                ans[i] += upper_bound(p+1,p+1+n,a) - lower_bound(p+1,p+1+n,a);
            }
        }
        for(int i = 1;i <= n;i++){
            memcpy(p+1,q+1,sizeof(point)*n);
            o = p[i];
            swap(p[i],p[n]);
            sort(p+1,p+n);
            for(int k = n+1;k <= ma;k++){
                int x = p[k].x - o.x,y = p[k].y - o.y;
                point a = point(o.x-y,o.y+x),b = point(o.x+y,o.y-x);
                ans[p[k].id] += upper_bound(p+1,p+n,a) - lower_bound(p+1,p+n,a);
                ans[p[k].id] += upper_bound(p+1,p+n,b) - lower_bound(p+1,p+n,b);
            }
        }
        for(int i = n+1;i <= ma;i++)printf("%d\n",ans[i]);
    }
    return 0;
}

总结

Angel Beats?Angle Beats?

音无结弦之时,天使跃动之心。立于浮华之世,奏响天籁之音。

做出就是金银,做不出就是废铜。

你可能感兴趣的:(计算几何,ACM,计算几何,极角排序,CCPC,CCPC秦皇岛)