【LOJ】#2082. 「JSOI2016」炸弹攻击 2

题解

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

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

代码

#include <bits/stdc++.h>
#define enter putchar('\n')
#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了呢。。

posted @ 2018-08-29 18:44  sigongzi  阅读(202)  评论(0编辑  收藏  举报