CCPC秦皇岛gym102361A. Angle Beats
题意:
给你n个点的坐标,现在有q次询问,每次询问给你一个坐标,问这个坐标可以与给定的n个点组成多少个不同的直角三角形
n<=2000,q<=2000
题解:
正解貌似是用极角排序后尺取得到答案,但我看很多人有更简便的方法
对于每次询问,我们可以分别考虑被询问点是直角点还是非直角点
如果是直角点,我们可以先将n个点与被询问点的斜率存下来,然后再循环n个点,看有多少个点是可以构成直线(即斜率乘积为-1)
如果是非直角点,我们可以直接n2n^2n2枚举n个点,然后判断是否可以构成直角
这个题原理很简单,细节很多,首先斜率直接存很麻烦,我们存横纵坐标。其次map跑的很慢,因此加map的值时可以先判断map中是否存有对应的参数,否则会T
详细见代码
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
bool Handsome;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test(bool &Most)
{
#ifdef ONLINE_JUDGE
#elseprintf("%.2lfMB\n",(&Most-&Handsome)/1024.0/1024.0);startTime = clock ();freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=2e4+9;
bool Most;
struct Point{ll x,y;Point(){}Point(ll _x,ll _y){x=_x;y=_y;}void input(){read(x,y);}Point update()const{if(x<0||(x==0&&y<0))return Point(-x,-y);else return Point(x,y);}bool operator<(const Point &b)const{Point A=update(),B=b.update(); return A.x*B.y<A.y*B.x;}Point operator-(const Point &b)const{return Point(x-b.x,y-b.y); }
}point[maxn];
int ans[maxn];
map<Point,int>mp;
vector<Point>vec;
int main()
{rd_test(Most);int n,q;read(n,q);for(int i=1;i<=n;i++)point[i].input();for(int i=0;i<q;i++){mp.clear();Point q;q.input();vec.push_back(q);for(int j=1;j<=n;j++)mp[point[j]-q]++;for(auto it:mp){Point tmp(-it.first.y,it.first.x);if(mp.count(tmp))ans[i]+=mp[tmp]*it.second;}ans[i]/=2;}for(int i=1;i<=n;i++){//n个点分别为直角 mp.clear();for(int j=1;j<=n;j++){if(i==j)continue;mp[point[j]-point[i]]++;}for(int j=0;j<q;j++){Point tmp=vec[j]-point[i];tmp=Point(-tmp.y,tmp.x);if(mp.count(tmp))ans[j]+=mp[tmp];}}for(int i=0;i<q;i++)printf("%d\n",ans[i]);
// cout<<ans[i]<<endl; //Time_test();
}