Codeforces 429D Tricky Function(平面最近点对)

题目链接  Tricky Function

$f(i, j) = (i - j)^{2} + (s[i] - s[j])^{2}$

把$(i, s[i])$塞到平面直角坐标系里,于是转化成了平面最近点对问题。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 100010;

struct Point{
	LL x, y;
	void scan(){ scanf("%lld%lld", &x, &y);}
} p[N], q[N];

int n;
LL c[N];
LL s;

bool cmp_x(const Point &a, const Point &b){
	return a.x < b.x;
}
bool cmp_y(const Point &a, const Point &b){
	return a.y < b.y;
}

LL dist(const Point &a, const Point &b){
	return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

LL work(int l, int r){
	if (r == l) return 9e18;
	if (r - l == 1) return dist(p[l], p[r]);
	if (r - l == 2) return min(min(dist(p[l], p[r]), dist(p[l + 1], p[r])), dist(p[l], p[l + 1]));
	int mid = (l + r) >> 1, cnt = 0;
	LL ret = min(work(l, mid), work(mid + 1, r));

	rep(i, l, r) if (p[i].x < p[mid].x + sqrt(ret) && p[i].x > p[mid].x - sqrt(ret)) q[++cnt] = p[i];
	sort(q + 1, q + cnt + 1, cmp_y);
	rep(i, 1, cnt - 1) rep(j, i + 1, cnt){
		if ((q[j].y - q[i].y) * (q[j].y - q[i].y) > ret) break;
		ret = min(ret, dist(q[i], q[j]));
	}

	return ret;
}

int main(){

	scanf("%d", &n);
	rep(i, 1, n) scanf("%lld", c + i);
	rep(i, 1, n){
		s += c[i];
		p[i] = {i, s};
	}
	sort(p + 1, p + n + 1, cmp_x);
	printf("%lld\n", work(1, n));
	return 0;

}

  

时间: 2024-10-17 00:53:01

Codeforces 429D Tricky Function(平面最近点对)的相关文章

Codeforces 429D Tricky Function 最近点对

题目链接:点击打开链接 暴力出奇迹. 正解应该是最近点对,以i点为x轴,sum[i](前缀和)为y轴,求任意两点间的距离. 先来个科学的暴力代码: #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> #include<iostream> #include<queue> using namespace std; #define N 10005

Codeforces 429D Tricky Function 近期点对

题目链接:点击打开链接 暴力出奇迹. 正解应该是近期点对.以i点为x轴,sum[i](前缀和)为y轴,求随意两点间的距离. 先来个科学的暴力代码: #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> #include<iostream> #include<queue> using namespace std; #define N 10005

codeforces 429D Tricky Function

这道就是相当于i表示x轴,sum[i]表示y轴,sum[i]表示前i个数的和 那么计算最小两点之间的距离 所谓的就是看了题解恍然大悟的题,就是算的时候先算的j->i的距离, #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; #define N 11111 ll a

【Codeforces 429D】 Tricky Function

[题目链接] http://codeforces.com/problemset/problem/429/D [算法] 令Si = A1 + A2 + ... + Ai(A的前缀和) 则g(i,j) = Sj - Si f(i,j) = (i-j)^2 + (Si - Sj)^2 观察这个式子,我们发现可以用类似于平面最近点对的算法来求解该问题 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 100010 const

Codeforces Round #245 (Div. 1)——Tricky Function

l and dished out an assist in the Blackhawks' 5-3 win over the Nashville Predators.Shaw said just playing with the Blackhawks was enough motivation for him."Positive, I'm playing in the NHL," Shaw said after Sunday's win. "What can't you be

hdu1007 平面最近点对(暴力+双线程优化)

突发奇想,用双线程似乎可以优化一些暴力 比如说平面最近点对这个题目,把点复制成2份 一份按照x排序,一份按照y排序 然后双线程暴力处理,一份处理x,一份处理y 如果数据利用x递减来卡,那么由于双线程,它卡不住y 如果数据利用y递减来卡,那么卡不住x 这样暴力n^2就可以过了 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algori

平面最近点对(分治nlogn)

平面最近点对,是指给出平面上的n个点,寻找点对间的最小距离 首先可以对按照x为第一关键字排序,然后每次按照x进行分治,左边求出一个最短距离d1,右边也求出一个最短距离d2,那么取d=min(d1, d2) 然后只需考虑横跨左右两侧的点,不妨枚举左侧的点pi 那么很显然的是如果pi距离中间的点超过了d,便可以直接舍去,只需考虑距离中间点小于d的点 这样一来就可以对每个pi画一个边长为2d的正方形,易证,矩形内最多存在8个点. 那么关键问题就是要快速找这8个点 朴素做法是对分治后的点进行快排,这样复

POJ 3714 Raid(平面最近点对)

解题思路: 分治法求平面最近点对,点分成两部分,加个标记就好了. #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <iomanip>

平面最近点对

HDU 1007 求平面最近点对距离的一半 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-7; const int MAXN = 100010; const double INF = 1e20; struct Point