HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4
比赛时会错题意+不知道怎么线段树维护分数- -
思路来自题解
/*
HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training Contest 4
题意:
给出 a[N];
设 size(l,r)为区间(l,r)不同数字的个数,求 size(l,r)/(r-l+1) 的最小值
限制: N <= 6e5, a[i] <= 6e5
分析:
二分答案 mid
则判定条件为是否存在 size(l,r)/(r-l+1) <= mid
变换一下: size(l,r) + mid*l <= mid * (r+1)
将左式存入线段树中,枚举 r,对某段 l 进行更新(last[a[r]+1] 到 r),更新操作为值+1
再对每个 r 判断一下上式是否成立
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 6e4+5;
const double eps = 1e-5;
const double INF = 1e18;
namespace SegT {
double val[N];
double Min[N<<2]; int add[N<<2];
void up(int x) {
Min[x] = min(Min[x<<1], Min[x<<1|1]);
}
void down(int x) {
if (add[x]) {
add[x<<1] += add[x];
Min[x<<1] += add[x];
add[x<<1|1] += add[x];
Min[x<<1|1] += add[x];
add[x] = 0;
}
}
void build(int l, int r, int x) {
add[x] = 0;
if (l == r) {
Min[x] = val[l]; return;
}
int mid = (l+r) >> 1;
build(l, mid, x<<1);
build(mid+1, r, x<<1|1);
up(x);
}
void change(int L, int R, int num, int l, int r, int x) {
if (L <= l && r <= R) {
add[x] += num;
Min[x] += num;
return;
}
down(x);
int mid = (l+r) >> 1;
if (L <= mid) change(L, R, num, l, mid, x<<1);
if (mid < R) change(L, R, num, mid+1, r, x<<1|1);
up(x);
}
double query(int L, int R, int l, int r, int x) {
if (L <= l && r <= R) return Min[x];
down(x);
int mid = (l+r) >> 1;
double res = INF;
if (L <= mid) res = min(res, query(L, R, l, mid, x<<1));
if (R > mid) res = min(res, query(L, R, mid+1, r, x<<1|1));
return res;
}
}
int t, n, a[N];
int last[N];
bool solve(double mid)
{
for (int i = 1; i <= n; i++)
SegT::val[i] = i*mid;
SegT::build(1, n, 1);
memset(last, 0, sizeof(last));
for (int i = 1; i <= n; i++)
{
SegT::change(last[a[i]]+1, i, 1, 1, n, 1);
last[a[i]] = i;
double res = SegT::query(1, i, 1, n, 1);
if (res < (i+1)*mid - eps) return 1;
}
return 0;
}
double BinaryFind(double l, double r)
{
double mid;
while ((r-l) > eps) {
mid = (l+r) / 2;
if (solve(mid)) r = mid;
else l = mid;
}
return mid;
}
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
printf("%.9f\n", BinaryFind(0, 1));
}
}
我自倾杯,君且随意

浙公网安备 33010602011771号