[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^2\log 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\n", ans * 4ll);
return 0;
}

[LOJ3054] 「HNOI2019」鱼的更多相关文章

  1. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

  2. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

  3. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  4. Loj 3058. 「HNOI2019」白兔之舞

    Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...

  5. Loj #3057. 「HNOI2019」校园旅行

    Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...

  6. 【loj - 3056】 「HNOI2019」多边形

    目录 description solution accepted code details description 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时 ...

  7. 【loj - 3055】「HNOI2019」JOJO

    目录 description solution accepted code details description JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或 ...

  8. LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分

    题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...

  9. LOJ 3057 「HNOI2019」校园旅行——BFS+图等价转化

    题目:https://loj.ac/problem/3057 想令 b[ i ][ j ] 表示两点是否可行,从可行的点对扩展.但不知道顺序,所以写了卡时间做数次 m2 迭代的算法,就是每次遍历所有不 ...

随机推荐

  1. 如何在VMware Workstation上安装CentOS_7

    1.首先打开VMware Workstation-文件-新建虚拟机 2.选择自定义向导,下一步. 3.由于我的软件版本比较高,不想太多硬件限制就选了版本11.也可以选择低一些版本的,这样兼容性会更好, ...

  2. 深入理解JVM - 线程安全与锁优化 - 第十三章

    线程安全 当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对 ...

  3. 基于深度学习的安卓恶意应用检测----------android manfest.xml + run time opcode, use 深度置信网络(DBN)

    基于深度学习的安卓恶意应用检测 from:http://www.xml-data.org/JSJYY/2017-6-1650.htm 苏志达, 祝跃飞, 刘龙     摘要: 针对传统安卓恶意程序检测 ...

  4. centos7搭建mysql-5.7.22主从复制

    mysql7.7.22主从复制 本项目是根据真实环境搭建编写出文档,文档中的目录也是根据自己公司环境所创建.公司原来是一台服务器搭建的数据库(5.7.22),由于业务的扩展需要搭建一台从服务器,减轻主 ...

  5. Mybatis-Generator_学习_01_mybatis-generator笔记

    一.generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ...

  6. 改变Ecplise项目窗口字体样式

    Eclipse\plugins\org.eclipse.ui.themes_1.1.1.v20151026-1355\css e4-dark_win.css CTabFolder Tree, CTab ...

  7. 网络编程学习笔记-MAC地址和IP地址的关系

    简单地说:ip地址是服务商给你的,mac地址是你的网卡物理地址. 一.IP地址 对于IP地址,相信大家都很熟悉,即指使用TCP/IP协议指定给主机的32位地址.IP地址由用点分隔开的4个8八位组构成, ...

  8. BZOJ - 4518: 征途(斜率优化,求N数划分为M区间的最小方差)

    注意初始化...等等补 #include<bits/stdc++.h> #define ll long long using namespace std; ; int q[maxn],he ...

  9. mac hosts

    1 在命令行中输入:sudo vim /etc/hosts. 2 输入开机密码,就可打开文件.按下键盘i,对文件进入可编辑状态. 3 修改完,先按esc退出编辑模式,之后,按shift+:,再按wq来 ...

  10. 兼容ie6,ie7,ie8,firefox,chrome浏览器的代码片段

    hack实现方式和原理 #hacker{ color:red; *color:white; /*for ie6,ie7*/ *+color:blue; /*for ie7*/ _color:gray; ...