GCJ2015FinalC

题意

给长度为 \(n\)\(01\)\(s\),和比例 \(r\)
\(s\) 的子串中 \(|\frac{1 的个数}{长度} - r|\) 最小是多少,输出子串的开始位置,若有多个起始位置合法,输出最小的。

\(1\ \leq\ n\ \leq\ 10^5\)

做法1

\(cnt1_i\) 表示 \(s[i...n]\)\(1\) 的个数,\(len_i\) 表示 \(s[i...n]\) 的长度。
一个子串可以表示为两个后缀 \(i,\ j\) 相减得到,\(1\) 的比例为 \(\frac{cnt1_i\ -\ cnt1_j}{len_i\ -\ len_j}\)
在坐标系中考虑,问题变成平面上 \(n\) 个点,两两连线,找最接近 \(r\) 的斜率的直线。按照 \(y\ =\ rx\ +\ k\)\(k\) 值排序即可。

时间复杂度 \(O(n\ log\ n)\)

代码

#include <bits/stdc++.h>

#define eps 1e-10
#define double long double

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

struct Num {
	long long zi, mu;

	Num() {}
	Num(long long zi, long long mu): zi(zi), mu(mu) {}

	friend bool operator < (const Num &a, const Num &b) {
		double t = (double) a.zi * b.mu - (double) a.mu * b.zi;
		return t < -eps;
	}

	friend bool operator == (const Num &a, const Num &b) {
		double t = (double) a.zi * b.mu - (double) a.mu * b.zi;
		return t >= -eps && t <= eps;
	}
};

int main() {
	ios::sync_with_stdio(false);
	int T;
	cin >> T;
	for (int i = 1; i <= T; ++i) {
		cout << "Case #" << i << ": ";
		int n;
		string s;
		double r;
		cin >> n >> r >> s;
		int R = 1000000 * r;
		vector<int> ord(n + 1), x(n + 1, 0), y(n + 1, 0);
		for (int i = 0; i <= n; ++i) ord[i] = i;
		for (int i = n - 1; ~i; --i) {
			x[i] = x[i + 1] + 1;
			y[i] = y[i + 1] + (s[i] == '1');
		}
		sort(ord.begin(), ord.end(), [&](int i, int j) {
				long long ki = (long long) 1000000 * y[i] - (long long) R * x[i];
				long long kj = (long long) 1000000 * y[j] - (long long) R * x[j];
				if(ki == kj) return i < j;
				else return ki < kj;
				});
		Num mn(1, 1);
		int ans;
		for (int _ = 0; _ < n; ++_) {
			bool output = 0;
			if(i == 27) output = 1;
			int i = ord[_], j = ord[_ + 1];
			if(i > j) swap(i, j);
			Num k(1000000ll * (y[i] - y[j]), 1000000ll * (x[i] - x[j]));
			k.zi -= (long long) R * (x[i] - x[j]);
			if(k.zi < 0) k.zi = -k.zi;
			if(k == mn) ans = min(ans, i);
			else if(k < mn) mn = k, ans = i;
		}
		cout << ans << endl;
	}
	return 0;
}
posted @ 2018-11-30 19:59  King_George  阅读(241)  评论(0编辑  收藏  举报