101992 I

傻逼题,1000个点问你面积在[L,R]内的直角三角形有多少个

好像大家都用的gcd,甚至atan2什么的。。。

不过我受到去年北京J的毒害,全程用的整形。

枚举顶点,极角排序,双指针扫一下,然后对每个存一下这个区间[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

 

posted @ 2019-05-02 17:57  MXang  阅读(139)  评论(0编辑  收藏  举报