• [LOJ3054] 「HNOI2019」鱼


    [LOJ3054] 「HNOI2019」鱼

    链接

    链接

    题解

    首先想 (O(n^3)) 的暴力,不难发现枚举 (A)(D) 后, ((B,C))((E,F)) 两组点互相之间没有影响,因此可以分开计算,对于任意一组点,枚举其中一个点,另一个点即为枚举的点关于 (AD) 的对称点,暴力统计即可

    然后首先考虑 ((E,F)) 一组点。由于有 (angle ADE, angle ADF gt 90 degree) 的限制,那么 (E,F) 两个点被限制在一个半平面内。考虑先枚举 (D) 再按照极角序枚举 (A),那么每个点进入可用半平面一次离开可用半平面一次,复杂度 (O(n^2))

    下面考虑 ((B, C)) 一组点。如果 (A,D) 确定了,那么相当于确定了 (BC) 的斜率。可以预处理枚举所有的 (B,C) 并按斜率归类,并且由于每一组 (B,C) 的斜率都相同,那么其所能对应的 (AD) 的斜率也相同,又 (BC) 的中点在 (AD) 上,所以对于确定的 (BC) 可以确定出 (AD) 所在直线。按照所在直线归类,每一类中按照 (BC) 的中点的 (x) 坐标排序,那么当 (AD) 确定时,仅需在其对应的一类中查询中点坐标在 (AD) 之间的所有 (B,C) 并统计个数,可以二分出结果,复杂度 (O(n^2log n^2))

    代码

    // Copyright lzt
    #include <stdio.h>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <set>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <string>
    #include <ctime>
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<long long, long long> pll;
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define rep(i, j, k) for (register int i = (int)(j); i <= (int)(k); i++)
    #define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
    #define Debug(...) fprintf(stderr, __VA_ARGS__)
    
    inline ll read()
    {
      ll x = 0, f = 1;
      char ch = getchar();
      while (ch < '0' || ch > '9')
      {
        if (ch == '-')
          f = -1;
        ch = getchar();
      }
      while (ch <= '9' && ch >= '0')
      {
        x = 10 * x + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    struct P
    {
      long long x, y;
      long long len() { return 1ll * x * x + 1ll * y * y; }
    } a[1009];
    
    long long ans;
    vector<int> p[1009][1009], v[1009][1009];
    long long n, id[1009], nw, cnt[1009][1009][2], CNT, po, PO, tot, val[1000061], ID[1000061];
    P dir[1000061];
    bool bo[1009];
    
    int nxt(int x) { return x == n ? 2 : x + 1; }
    long long operator^(P a, P b) { return 1ll * a.x * b.y - 1ll * a.y * b.x; }
    P operator-(P a, P b) { return (P){a.x - b.x, a.y - b.y}; }
    P operator*(P a, int b) { return (P){a.x * b, a.y * b}; }
    bool cmp(int x, int y) { return (a[x] - a[nw]).len() < (a[y] - a[nw]).len(); }
    bool check(int x) { return a[x].x > a[nw].x || a[x].x == a[nw].x && a[nw].y < a[x].y; }
    bool CHECK(int x) { return dir[x].x > a[nw].x || dir[x].x == a[nw].x && a[nw].y < dir[x].y; }
    bool Check(P x) { return x.x > a[nw].x || x.x == a[nw].x && a[nw].y < x.y; }
    bool Check2(P x) { return x.x > a[nw].x || x.x == a[nw].x && a[nw].y > x.y; }
    
    bool CMP(int x, int y)
    {
      if (check(x) ^ check(y))
        return check(x);
      return ((a[x] - a[nw]) ^ (a[y] - a[nw])) < 0;
    }
    
    bool PMC(int x, int y)
    {
      if (CHECK(x) ^ CHECK(y))
        return CHECK(x);
      return ((dir[x] - a[nw]) ^ (dir[y] - a[nw])) < 0;
    }
    
    bool Cmp(P x, P y)
    {
      if (Check(x) ^ Check(y))
        return Check(x);
      return ((x - a[nw]) ^ (y - a[nw])) <= 0;
    }
    
    bool Cmp2(P x, P y)
    {
      if (Check2(x) ^ Check2(y))
        return Check2(x);
      return ((x - a[nw]) ^ (y - a[nw])) < 0;
    }
    
    void ins(int j)
    {
      if (bo[j])
        return;
      bo[j] = 1;
      for (int k = 0, sz = v[nw][j].size(); k < sz; k++)
        if (bo[v[nw][j][k]])
          CNT++;
    }
    void del(int j)
    {
      if (!bo[j])
        return;
      bo[j] = 0;
      for (int k = 0, sz = v[nw][j].size(); k < sz; k++)
        if (bo[v[nw][j][k]])
          CNT--;
    }
    
    int main()
    {
      scanf("%lld", &n), ans = 0;
      for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &a[i].x, &a[i].y);
      for (int i = 1; i <= n; i++)
      {
        for (int j = 1; j <= n; j++)
          id[j] = j;
        nw = i, sort(id + 1, id + 1 + n, cmp);
        for (int j = 2; j <= n; j++)
          for (int k = j - 1; (a[id[j]] - a[nw]).len() == (a[id[k]] - a[nw]).len(); k--)
            if (((a[id[j]] - a[nw]) ^ (a[id[k]] - a[nw])) != 0)
            {
              tot = 0;
              if (id[j] > id[k])
                swap(j, k), tot = 1;
              p[id[j]][id[k]].push_back(i), v[i][id[j]].push_back(id[k]), v[i][id[k]].push_back(id[j]);
              if (tot)
                swap(j, k);
            }
      }
      for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
        {
          cnt[i][j][0] = cnt[i][j][1] = 0;
          for (int k = 0, sz = p[i][j].size(); k < sz; k++)
            if (((a[i] - a[j]) ^ (a[i] - a[p[i][j][k]])) > 0)
              cnt[i][j][0]++;
            else
              cnt[i][j][1]++;
        }
      for (int i = 1; i <= n; i++)
      {
        n += 8;
        memset(bo, 0, sizeof(bo)), tot = 1;
        for (int j = 1; j <= n - 8; j++)
          if (i != j)
            id[++tot] = j;
        a[id[++tot] = (n - 7)] = (P){a[i].x + 1, a[i].y};
        a[id[++tot] = (n - 6)] = (P){a[i].x, a[i].y - 1};
        a[id[++tot] = (n - 5)] = (P){a[i].x - 1, a[i].y};
        a[id[++tot] = (n - 4)] = (P){a[i].x, a[i].y + 1};
        a[id[++tot] = (n - 3)] = (P){a[i].x + 1, a[i].y + 1};
        a[id[++tot] = (n - 2)] = (P){a[i].x + 1, a[i].y - 1};
        a[id[++tot] = (n - 1)] = (P){a[i].x - 1, a[i].y - 1};
        a[id[++tot] = n] = (P){a[i].x - 1, a[i].y + 1};
        nw = i, sort(id + 2, id + 1 + n, CMP), CNT = 0, po = n;
        for (int j = 2; j <= n; j++)
          if (a[id[j]].x > a[i].x)
            ins(id[po = j]);
        PO = 2, tot = 0;
        rep(j, 1, n) rep(k, 1, n) {
          if (j == k) continue;
        }
        rep(j, 1, n) rep(k, 1, n) {
          if (j == k) continue;
        }
        rep(j, 1, n) rep(k, 1, n) {
          if (j == k) continue;
        }
        for (int j = 1; j <= n; j++)
          for (int k = 0, sz = v[i][j].size(), X; k < sz; k++)
            if (v[i][j][k] > j)
            {
              X = v[i][j][k];
              dir[++tot] = (P){a[j].x + a[X].x - a[i].x - a[i].x, a[j].y + a[X].y - a[i].y - a[i].y};
              dir[tot] = (P){a[i].x + dir[tot].y, a[i].y - dir[tot].x};
              if (((a[j] - a[X]) ^ (a[j] - a[i])) > 0)
                val[tot] = cnt[j][X][1];
              else
                val[tot] = cnt[j][X][0];
            }
        dir[++tot] = (P){a[i].x, a[i].y + 1}, val[tot] = 0;
        dir[++tot] = (P){a[i].x + 1, a[i].y}, val[tot] = 0;
        dir[++tot] = (P){a[i].x, a[i].y - 1}, val[tot] = 0;
        dir[++tot] = (P){a[i].x - 1, a[i].y}, val[tot] = 0;
        dir[++tot] = (P){a[i].x + 1, a[i].y + 1}, val[tot] = 0;
        dir[++tot] = (P){a[i].x + 1, a[i].y - 1}, val[tot] = 0;
        dir[++tot] = (P){a[i].x - 1, a[i].y - 1}, val[tot] = 0;
        dir[++tot] = (P){a[i].x - 1, a[i].y + 1}, val[tot] = 0;
        for (int j = 1; j <= tot; j++)
          ID[j] = j;
        sort(ID + 1, ID + 1 + tot, PMC);
        int en = nxt(po);
        bool BO = 0;
        for (int j = 2; j <= n; j++)
          if (!check(id[j]) || a[id[j]].x > a[i].x)
          {
            PO = j;
            break;
          }
        for (int j = 1; j <= tot; j++)
        {
          while ((!BO || nxt(po) != en) && Cmp2((P){a[i].x * 2 - dir[ID[j]].x, dir[ID[j]].y},
                                                (P){a[id[nxt(po)]].x, a[i].y * 2 - a[id[nxt(po)]].y}))
            BO = 1, ins(id[po = nxt(po)]);
          while (PO <= n && Cmp(a[id[PO]], dir[ID[j]]))
            del(id[PO]), PO++;
          ans += 1ll * CNT * val[ID[j]];
        }
        n -= 8;
      }
      printf("%lld
    ", ans * 4ll);
      return 0;
    }
    
  • 相关阅读:
    redis 5.0.5集群部署
    python 继承、多继承与方法重写(二)
    python 脚本监控硬件磁盘状态并发送报警邮件
    k8s 应用程序获取真实来源ip
    yolov5 安装尝试
    安装pygrib
    ubuntu编译ecodes
    python mpi实验
    mint install gaussian 16
    flask 使用工程外的static文件位置
  • 原文地址:https://www.cnblogs.com/wawawa8/p/10680572.html
Copyright © 2020-2023  润新知