您的位置:首页 > 其它

codeforces 883I Photo Processing

2017-12-28 19:01 169 查看
题目链接:http://codeforces.com/problemset/problem/883/I

题意:给一个大小为n(n <= 3e5)的数组,要求划分为不小于k个元素的集合,各个集合最大值最小值的差的最大值最小。

题解:最大值最小,用二分答案可以处理掉这个问题,但是验证不是朴素的直接扫过去贪心,而是要记录过去信息的dp。数组排序后,dp[i]代表从1到i能否完整划分,计算时,现算出a[i] - ans的位置,再找到i - k + 1的位置,看其中是否有解,这个区间我用前缀和来优化。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <functional>
#include <map>
#include <bitset>

#define INF 0x7fffffff
#define REP(i,j,k) for(int i = j;i <= k;i++)
#define squr(x) (x) * (x)
#define lowbit(x) (x&(-x))
#define getint(x) scanf("%d", &(x))

using namespace std;

typedef long long LL;
typedef pair<int, int> pii;

const int MAXN = 3e5 + 10;
int n, k;
int v[MAXN];
int f[MAXN];

int search(int num) {
int l = 1, r = n;
while (l < r) {
int mid = (l + r) / 2;
if (v[mid] < num) {
l = mid + 1;
} else {
r = mid;
}
}
return l;
}

bool check(int len) {
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++) {
int t = search(v[i] - len);
if (t == 1 && i - t + 1 >= k) {
if (i == n) {
return true;
}
f[i] += f[i - 1] + 1;
}else if (t >= 2 && i - t + 1 >= k && f[i - k] - f[t - 2] > 0) {
if (i == n) {
return true;
}
f[i] += f[i - 1] + 1;
} else {
f[i] = f[i - 1];
}
}
return false;
}

int main(int argc, const char * argv[]) {
getint(n); getint(k);
REP(i, 1, n) {
getint(v[i]);
}
sort(v + 1, v + 1 + n);
int l = 0, r = 1000000000;
while (l < r) {
int mid = (l + r) / 2;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
printf("%d\n", l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces dp