zoukankan      html  css  js  c++  java
  • 【LOJ】#2082. 「JSOI2016」炸弹攻击 2

    题解

    想到n3发现思路有点卡住了

    对于每个发射塔把激光塔和敌人按照极角排序,对于一个激光塔,和它转角不超过pi的激光塔中间夹的敌人总和就是答案
    记录前缀和,用two-Points扫一下就行

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 805
    #define mo 99994711
    #define pb push_back
    #define eps 1e-8
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef unsigned long long u64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 - '0' + c;
            c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    struct Point {
        db x,y;
        Point(){}
        Point(db _x,db _y) {x = _x;y = _y;}
        friend Point operator + (const Point &a,const Point &b) {return Point(a.x + b.x,a.y + b.y);}
        friend Point operator - (const Point &a,const Point &b) {return Point(a.x - b.x,a.y - b.y);}
        friend Point operator * (const Point &a,const db &d) {return Point(a.x * d,a.y * d);}
        friend Point operator / (const Point &a,const db &d) {return Point(a.x / d,a.y / d);}
        friend db operator * (const Point &a,const Point &b) {return a.x * b.y - a.y * b.x;}
        friend db dot(const Point &a,const Point &b) {return a.x * b.x + a.y * b.y;}
        db norm() {return sqrt(x * x + y * y);}
        friend bool operator < (const Point &a,const Point &b) {return a.x < b.x || (a.x == b.x && a.y < b.y);}
    }D1[MAXN],S1[MAXN],T1[MAXN];
    int D,S,T,tot;
    pair<db,Point> L[MAXN * 4];
    Point P[MAXN * 4];
    int sum[MAXN * 4];
    void Solve() {
        read(D);
        for(int i = 1 ; i <= D ; ++i) scanf("%lf%lf",&D1[i].x,&D1[i].y);
        read(S);
        for(int i = 1 ; i <= S ; ++i) scanf("%lf%lf",&S1[i].x,&S1[i].y);
        read(T);
        int64 ans = 0;
        for(int i = 1 ; i <= T ; ++i) scanf("%lf%lf",&T1[i].x,&T1[i].y);
        for(int i = 1 ; i <= S ; ++i) {
            tot = 0;
            for(int j = 1 ; j <= D ; ++j) L[++tot] = mp(atan2(D1[j].y - S1[i].y,D1[j].x - S1[i].x),D1[j]);
            for(int j = 1 ; j <= T ; ++j) L[++tot] = mp(atan2(T1[j].y - S1[i].y,T1[j].x - S1[i].x),T1[j]);
            sort(L + 1,L + tot + 1);
            for(int i = 1 ; i <= tot ; ++i) P[i] = L[i].se;
            for(int i = 1 ; i <= tot ; ++i) P[i + tot] = L[i].se;
            tot *= 2;
            for(int i = 1 ; i <= tot ; ++i) {
                sum[i] = sum[i - 1];
                if(P[i].y > 0) sum[i]++;
            }
            int r = 0,cnt = 0;
            int64 s = 0;
            for(int l = 1 ; l <= tot / 2; ++l) {
                while(r < l) {if(P[r + 1].y < 0) s += sum[r + 1],++cnt;++r;}
                while((P[l] - S1[i]) * (P[r + 1] - S1[i]) > 0) {
                    if(P[r + 1].y < 0) s += sum[r + 1],++cnt;++r;
                }
                if(P[l].y < 0) {
                    s -= sum[l];--cnt;
                    ans += s - 1LL * cnt * sum[l];
                }
            }
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    貌似板刷了一页LOJ了呢。。

  • 相关阅读:
    二分与三分
    NOIP应试技巧
    数论
    并差集
    最短路
    图的遍历

    最小生成树
    树状数组
    线段树
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9556242.html
Copyright © 2011-2022 走看看