首页 > 其他分享 >CF1025F Disjoint Triangles

CF1025F Disjoint Triangles

时间:2023-11-01 17:12:42浏览次数:35  
标签:直线 const int CF1025F vec Disjoint 三角形 rh Triangles

虽然我不懂计算几何,但是两个三角形互相进入,感觉很涩啊! —— By 【】

考虑两个互不相交的三角形,寻找一个方式能够不重不漏地统计它们。

容易发现两条不交的线段 \(A_1A_2,B_1B_2\) 之间,必然存在一条直线将 \(A_1A_2,B_1B_2\) 分在直线两端,且与 \(A_1A_2,B_1B_2\) 无交。证明的话,随意将 \(A_1A_2\) 或者 \(B_1B_2\) 线段向对方平移一小段即可。我们发现三角形也存在这样的性质,也就是两个不交的三角形之间必然存在一条直线把它们分到直线两侧,证明同理。

事实上这样的直线有无限条,拎出任意一条这样的直线 \(l\) 进行旋转,发现最后这条直线 \(l'\) 会过两个三角形至少 \(2\) 个顶点,且这样的直线 \(l'\) 只有 \(2\) 条(一条顺时针旋转,一条逆时针旋转),如图:

我们可以找到一条两个三角形之间的蓝色直线 \(l\),顺时针旋转得到直线 \(l_1:BD\),逆时针旋转得到直线 \(l_2:CD\)。

于是我们就可以枚举 \(l_1,l_2\) 了,具体地:

  • 枚举直线 \(l\) 的一个端点 \(P_x\),将 \(P_x\) 当作坐标原点,对所有向量 \(\overrightarrow{P_xP_y}(y\in \{1,2,\cdots ,x-1,x+1,\cdots ,n\})\) 进行极角排序。
  • 对于一条直线 \(P_xP_y\),考虑统计以 \(P_xP_y\) 作为 \(l_1/l_2\) 的三角形对。设在 \(P_xP_y\) 上方的点的个数为 \(c\),那么合法的三角形对数为 \(2\dbinom{c}{2}\dbinom{n-2-c}{2}\)(乘 \(2\) 是因为同一边的两个点既可以连 \(P_x\) 也可以连 \(P_y\))。
  • 由于已经进行极角排序,所以顺序枚举所有 \(P_xP_y\),然后双指针就可以动态维护 \(c\),统计答案即可。

最后每个三角形对被 \(l_1\) 算了一遍,被 \(l_2\) 也算了一遍。所以答案要除以 \(2\)。

复杂度 \(O(n^2\log n)\)。

// Problem: F. Disjoint Triangles
// Contest: Codeforces - Codeforces Round 505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
// URL: https://codeforces.com/problemset/problem/1025/F
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define mt make_tuple
#define mp make_pair
#define fi first
#define se second

using namespace std;
typedef double db;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int> tu;
bool Mbe;

const int N = 2e3 + 200;
const db Pi = acos(-1);

struct vec {
	int x, y;
	vec () { }
	vec (int _x, int _y) : x(_x), y(_y) { }
	vec operator + (const vec &rh) const { return vec(x + rh.x, y + rh.y); }
	vec operator - (const vec &rh) const { return vec(x - rh.x, y - rh.y); }
	vec operator - () const { return vec(-x, -y); }
	db arc() { return atan2(y, x); }
} a[N], b[N];
int n;
db d[N];

int f(int x) { return x * (x - 1) / 2; }
ll calc(int x) {
	vector<int> dn, up;
	for (int i = 1; i <= n; i++) {
		if (i == x) continue;
		b[i] = a[i] - a[x], d[i] = b[i].arc();
		if (d[i] <= 0) dn.pb(i);
		else up.pb(i);
	}
	ll res = 0;
	sort(dn.begin(), dn.end(), [](int &x, int &y) { return d[x] < d[y]; });
	sort(up.begin(), up.end(), [](int &x, int &y) { return d[x] < d[y]; });
	for (int i = 0, j = 0, ct = up.size(); i < dn.size(); i++) {
		while (j < up.size() && d[up[j]] <= Pi + d[dn[i]]) j++, ct--;
		if (i) ct++; res += 1ll * f(ct) * f(n - 2 - ct);
	}
	return res;
}

void solve() {
	cin >> n;
	for (int i = 1, x, y; i <= n; i++)
		cin >> x >> y, a[i] = vec(x, y);
	ll res = 0;
	for (int i = 1; i <= n; i++) res += calc(i);
	cout << res << '\n';
}

bool Med;
int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cerr << (&Mbe - &Med) / 1048576.0 << " MB\n";
	#ifdef FILE
		freopen("1.in", "r", stdin);
		freopen("1.out", "w", stdout);
	#endif
	int T = 1;
	// cin >> T;
	while (T--) solve();
	cerr << (int)(1e3 * clock() / CLOCKS_PER_SEC) << " ms\n";
	return 0;
}

标签:直线,const,int,CF1025F,vec,Disjoint,三角形,rh,Triangles
From: https://www.cnblogs.com/Ender32k/p/17803572.html

相关文章

  • 不修改Read/Write Enabled,Texture.GetPixels,Mesh.triangles
    ###原理:将Texture拷贝一份出来然后读取///<summary>///不通过设置Read/WriteEnabled,直接克隆一份可读的Texture2D///</summary>///<paramname="source"></param>///<returns></returns>publicstaticTexture2DCloneTexture......
  • CF553C Love Triangles
    很有意思的一个题,想了一会才发现解题的关键首先我们注意到对于某个大小\(\ge3\)的连通块,其实连通块内的所有边的颜色都会被已知的边唯一确定而不同的连通块间的连边方式有两种,因此设连通块个数为\(tot\),最后的答案就是\(2^{tot-1}\)但还要考虑判掉不合法的情况,注意到不管是\(1......
  • 并查集(Disjoint Set)
    并查集是算法竞赛中常用的一种数据结构。其主要功能是查询两个元素是否在同一个集合以及将两个集合合并。第一部分并查集的基本操作算法思想我们将所有元素建成很多树(森林),每一棵树就是一个集合,比如下图有\(\{1,2,3,4,5,6\},\{7,9,10,11,12,13\}\)两个集合。......
  • 05 Rasterization (Triangles)
    1.ScreenPixel(RGB0-255)ScreenSpaceViewportTransform将屏幕进行缩放,然后将重心平移到原点,得到视口变换矩阵:2.Triangles最基础的多边形,任意多边形可以拆成三角形,三角形一定是平面图形,三角形内外定义清晰并可用叉积辨别(像素中心点),三角形内部属性可用三个点的属性由......
  • UVa 10112 Myacm Triangles (枚举&计算几何)
    10112-MyacmTrianglesTimelimit:3.000secondshttp://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=101&page=show_problem&problem=1053TherehasbeenconsiderablearcheologicalworkontheancientMyacmculture......
  • Disjoint-Set-Union Sum (诈骗题)(区间DP, 位置顺序!!!!)
    题目大意: 给出一个序列P,n个点每次可以选择2个相邻区间进行合并,会产生一个贡献值,当然合并n-1就合并完了,问在所有的情况下,贡献和是多少  思路:易错点:这个所有情况,你枚举的合并的那个先后顺序是有关系的!!!因此直接去区间dp只能把各个合并的情况给弄......
  • 【CF52B】Right Triangles
    updateon2022.04.26:修改了一处炸掉的格式。一、题意题目给我们一个\(n\timesm\)的字符矩阵,求三个*为顶点且直角边水平或竖直的三角形。二、思路首先想到的显然是......
  • 并查集(Disjoint-Set)
    并查集目录并查集定义模板题目原题链接题目描述输入格式输出格式数据范围分析并查集基本原理实现步骤问题1问题2问题3优化代码实现定义并查集(Disjoint-Set)是一种可以......
  • hdu5135 Little Zu Chongzhi's Triangles --状压dp
    原题链接:​​http://acm.hdu.edu.cn/showproblem.php?pid=5135​​题意:n根木棒,组成若干三角形,求最大面积和。分析:把所有木棒升序排序,可以组成三角形所有的的组合利用位运算......
  • CF1119E Pavel and Triangles 题解
    题面PavelandTriangles题面翻译给定n种木棍,第i+1种有ai​个,长度为2^i,求用这些木棍可以同时拼出多少个三角形(不可重复使用同一根)输入第一行n,第二行n个整数a0,a1,a2.........