牛客练习赛60 几何带师

链接

点击跳转

题解

点击传送到出题人的题解

出题人用的树状数组,我这里开了个平衡树维护偏序,其实一样

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
const double pi = acos(-1);
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
#define sqr(x) ((x)*(x))
int sign(double x)
{
    if(x<-eps)return -1;
    if(x>eps)return 1;
    return 0;
}
struct point
{
    double x, y;
    point(double x, double y):x(x),y(y){}
    point(){}
}_;
struct vec
{
    point o; double x, y;
    vec(point o, double x, double y):o(o),x(x),y(y){}
    vec(){};
    vec operator+(vec v){return vec(_, x+v.x, y+v.y);} //向量和
    vec operator-(vec v){return vec(_, x-v.x, y-v.y);} //向量差
    double operator^(vec v){return x*v.y - v.x*y;} //向量内积
    double operator*(vec v){return x*v.x + y*v.y;} //向量外积
    vec operator*(double t){return vec(_, x*t, y*t);} //向量数乘
    double abs2(){return sqr(x)+sqr(y);}   //模的平方
    double abs(){return sqrt(abs2());}         //模
    vec rot(double th)   //逆时针旋转,精度很差
    {return vec(o, -sin(th)*y+cos(th)*x, cos(th)*y+sin(th)*x );}
    vec rot(double sinth, double costh)  //逆时针旋转,精度取决于sinth和costh
    {return vec(o, -sinth*y+costh*x, costh*y+sinth*x );}
    vec trunc(double l){return (*this)*(l/abs());}    //把向量v的长度改为l,方向不变
};
point operator+(point p, vec v){return point(p.x+v.x, p.y+v.y);} //点沿着向量方向平移
vec operator-(point p1, point p2){return vec(p2,p1.x-p2.x,p1.y-p2.y);}//用两点构造向量
bool on(point p, vec v){return sign((p-v.o)^v)==0;}   //点在直线上
point projection(point p, vec v){return v.o + v*((p-v.o)*v/v.abs2());}  //求投影点
int n;
point a, b, pt[maxn];
int main()
{
    int i;
    n = read();
    a.x=read(), a.y=read();
    b.x=read(), b.y=read();
    vec ab = b-a;
    double sinth = ab.y/ab.abs(), costh = ab.x/ab.abs();
    vector<pdd> v1, v2;
    rep(i,1,n)
    {
        double x(read()), y(read());
        auto v = ( point(x,y) - a ).rot(-sinth,costh);
        auto th1 = fabs(atan2(v.y,v.x)), th2 = pi-fabs(atan2(v.y,v.x-ab.abs()));
        if(sign(v.y)>0)v1.emb( make_pair(th1,th2) );
        else v2.emb( make_pair(th1,th2) );
    }
    ll ans(0);
    tree<pdd,null_type,less<pdd>,rb_tree_tag,tree_order_statistics_node_update> tr;
    
    tr.clear();
    sort(v1.begin(),v1.end());
    for(auto pr:v1)
    {
        auto ord = tr.order_of_key(pdd(pr.se,pr.fi));
        ans += ord;
        tr.insert(pdd(pr.se,pr.fi));
    }

    tr.clear();
    sort(v2.begin(),v2.end());
    for(auto pr:v2)
    {
        auto ord = tr.order_of_key(pdd(pr.se,pr.fi));
        ans += ord;
        tr.insert(pdd(pr.se,pr.fi));
    }

    tr.clear();
    sort(v1.begin(),v1.end(),greater<pdd>());
    sort(v2.begin(),v2.end());
    auto it = v2.begin();
    for(auto pr:v1)
    {
        while(it!=v2.end() and it->fi < pi - pr.fi )tr.insert( pdd(it->se,it->fi) ), it++;
        auto ord = tr.order_of_key( pdd(pi-pr.se,pr.fi) );
        ans += ord;
    }

    printf("%lld",ans);
    return 0;
}
发布了948 篇原创文章 · 获赞 77 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/105212532
今日推荐