码迷,mamicode.com
首页 > 其他好文 > 详细

101992 I

时间:2019-05-02 18:30:50      阅读:125      评论:0      收藏:0      [点我收藏+]

标签: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  */
View Code

 

101992 I

标签:style   names   type   题解   can   space   ext   max   display   

原文地址:https://www.cnblogs.com/MXang/p/10802895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!