hdu 6371 Angle Beats

http://acm.hdu.edu.cn/showproblem.php?pid=6731

一开始用long double lower_bound超时。。。然后去网上学习了一手分数类写法13s飘过。。。

似乎用斜率存unorderd_map可以接近O(n^2)?

考虑两种情况,一个是原先的点a[u]为直角,另一个是询问的点的b[u]为直角。

a[u]为直角,再枚举一个b[i]为端点,然后去除了a[u]的里面二分两个方向有多少个a[v]能形成直角

b[u]为直角,枚举一个a[i]为端点,然后二分一个方向有多少个a[v]为直角。

 

#include<bits/stdc++.h>
#define maxl 4010
using namespace std;

const long double eps=1e-14;
const long double pi=acos(-1.0);

struct point
{
    int x,y,id;
    point(int a=0,int b=0)
    {
        x=a;y=b;
    }
    point operator - (const point &b)const
    {
        return point(x-b.x,y-b.y);
    }
}a[maxl],b[maxl],ata[maxl],bta[maxl],o;

inline long long det(const point &a,const point &b)
{
    return 1ll*a.x*b.y-1ll*a.y*b.x;
}

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);
    int qb=Quadrant(b);
    if(qa!=qb) return qa<qb;
    return det(a,b)>0; 
}

int n,q;
int ans[maxl];

inline void prework()
{
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&b[i].x,&b[i].y);
        ans[i]=0;
    }
}

inline void mainwork()
{
    point t;int tx,ty;
    for(int i=1;i<=q;i++)
        bta[i]=b[i],bta[i].id=i;
    for(int u=1;u<=n;u++)
    {
        o=a[u];int cnt=0; 
        for(int i=1;i<=n;i++)
        if(i!=u)
			ata[++cnt]=a[i];
        sort(ata+1,ata+n);
        for(int i=1;i<=q;i++)
        {
            tx=bta[i].x-o.x;ty=bta[i].y-o.y;
            t=point(o.x-ty,o.y+tx);
            ans[bta[i].id]+=upper_bound(ata+1,ata+n,t)-lower_bound(ata+1,ata+n,t);
            t=point(o.x+ty,o.y-tx); 
            ans[bta[i].id]+=upper_bound(ata+1,ata+n,t)-lower_bound(ata+1,ata+n,t);
        }
    }
    for(int i=1;i<=n;i++)
    	ata[i]=a[i];
    for(int u=1;u<=q;u++)
    {
        o=b[u];
        sort(ata+1,ata+1+n);
        for(int i=1;i<=n;i++)
        {
            tx=a[i].x-o.x;ty=a[i].y-o.y;
            t=point(o.x-ty,o.y+tx);
            ans[u]+=upper_bound(ata+1,ata+1+n,t)-lower_bound(ata+1,ata+1+n,t);
        }
    }
}

inline void print()
{
    for(int i=1;i<=q;i++)
        printf("%d\n",ans[i]);
}

int main()
{
	//freopen("A.in","r",stdin);
    while(~scanf("%d%d",&n,&q))
    {
        prework();
        mainwork();
        print();
    }
    return 0;
}
//https://blog.csdn.net/qq_40859782/article/details/102367943

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值