标签:style names type 题解 can space ext max display
傻逼题,1000个点问你面积在[L,R]内的直角三角形有多少个
谨以此题解纪念队切gym第一次施展出过的人不多计算几何
(去年北京K比这个难100倍。)
话说我北京K到现在都没补过啊。。。
我的是n^2logn的 (貌似不少n^3都过去了)
枚举顶点,极角排序,双指针扫一下,然后对每个存一下这个区间[l,r],就是这个区间里的和它能组成直角三角形
然后在区间里二分判断面积就行
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long db; 4 int sign(db k){ 5 if (k>0) return 1; else if (k<0) return -1; return 0; 6 } 7 int cmp(db k1,db k2){return sign(k1-k2);} 8 struct point{ 9 db x,y; 10 point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} 11 point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} 12 point operator * (db k1) const{return (point){x*k1,y*k1};} 13 point operator / (db k1) const{return (point){x/k1,y/k1};} 14 db abs2(){return x*x+y*y;} 15 int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);} 16 }; 17 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} 18 db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} 19 int compareangle (point k1,point k2){//极角排序+&长度排序 20 if(k1.getP()==k2.getP()){ 21 if(sign(cross(k1,k2))==0){ 22 return k1.abs2()<k2.abs2(); 23 } 24 return sign(cross(k1,k2))>0; 25 } 26 return k1.getP()<k2.getP(); 27 } 28 int t,n;db L,R; 29 point p[1005]; 30 vector<point> v; 31 vector<pair<int,int>>g[1005]; 32 int slove(int id){ 33 int res = 0; 34 v.clear(); 35 for(int i=0;i<=n;i++)g[i].clear(); 36 for(int i=1;i<=n;i++){ 37 if(i==id)continue; 38 v.push_back(p[i]-p[id]); 39 } 40 sort(v.begin(),v.end(),compareangle); 41 int m = v.size(); 42 for(int i=0;i<m;i++)v.push_back(v[i]); 43 int l=0,r=0;// 44 for(int i=0;i<m;i++){ 45 l=max(l,i); 46 point _90 = {-v[i].y,v[i].x}; 47 while (l+1<i+m&&cross(v[l+1],_90)>0&&cross(v[i],v[l+1])>=0)l++;//l+1>=90 48 if(l+1<i+m&&cross(v[l+1],_90)==0&&dot(v[l+1],_90)>0){ 49 r = max(r,l+1); 50 while (r+1<i+m&&cross(v[r+1],_90)==0&&cross(v[r+1],v[i])<=0)r++; 51 g[i].push_back(make_pair(l+1,r));//[l+1,r]是直角 52 } 53 } 54 for(int i=0;i<m;i++){ 55 if(g[i].empty())continue; 56 int id1,id2; 57 l = g[i][0].first,r = g[i][0].second; 58 while (l<=r){ 59 int mid = l+r>>1; 60 if(cross(v[i],v[mid])>=L*2)r=mid-1; 61 else l=mid+1; 62 } 63 id1=l; 64 l = g[i][0].first,r = g[i][0].second; 65 while (l<=r){ 66 int mid=l+r>>1; 67 if(cross(v[i],v[mid])<=R*2)l=mid+1; 68 else r=mid-1; 69 } 70 id2=r; 71 res+=id2-id1+1; 72 } 73 return res; 74 } 75 int main(){ 76 freopen("points.in","r",stdin); 77 scanf("%d",&t); 78 while (t--){ 79 scanf("%d%lld%lld",&n,&L,&R); 80 for(int i=1;i<=n;i++){ 81 scanf("%lld%lld",&p[i].x,&p[i].y); 82 } 83 int ans = 0; 84 for(int i=1;i<=n;i++){ 85 ans+=slove(i); 86 // printf("%d\n",ans); 87 } 88 printf("%d\n",ans); 89 } 90 } 91 /** 92 1 93 7 7 9 94 0 0 95 2 0 96 0 2 97 10 0 98 0 10 99 3 3 100 3 -3 101 1000000000 102 1 103 7 5 15 104 0 0 105 2 0 106 0 2 107 10 0 108 0 10 109 3 3 110 3 -3 111 112 1 113 7 1 100 114 0 0 115 2 0 116 0 2 117 10 0 118 0 10 119 3 3 120 3 -3 121 */ 122 /** 123 1 5 1 1000000000000000000 124 0 1000000000 125 0 -1000000000 126 -1000000000 0 127 1000000000 0 128 0 0 129 */
标签:style names type 题解 can space ext max display
原文地址:https://www.cnblogs.com/MXang/p/10802895.html