您的位置:首页 > 其它

VK Cup 2018 Round 2 div2 C, D 题解 【思维题】

2018-03-26 11:51 696 查看
传送门

C: 给定n个严格递增的数, 要从中选择三个数, 再满足下标i< j < k, 且a[k] - a[i] <= U, 的两个限制下,问可以使这个a[k]-a[j]/a[k]-a[i]最大是多少.

思路:就是一道很简单的水题,只不过要进行一定的小推导, 首先我们要知道的是如果确定了i, k, 那么很明显j = i + 1; 因为这样才能使a[j] 最小, 即分子a[k]-a[j]越大, 所以我们现在应该解决如何确定i, k那么我们再次通过一些推导如果i, j确定, 那么k一定越大越好, 即如果X > Y , 那么一定有 X-a[j]/X-a[i] > Y-a[j]/Y-a[i], 又因为那个限制条件, 所以我们可以转换一下那个式子a[k] <= a[i] + U, 所以我们枚举i, 然后通过二分查找k, 取尽量大的k, 然后取max即可.

AC Code

const int maxn = 1e5+5;
int a[maxn];
void solve()
{
int n, u;
while(~scanf("%d%d", &n, &u)) {
for (int i = 1 ; i <= n ; i ++) {
scanf("%d", a+i);
}
db ans = -1;
int flag = 1;
for (int i = 1 ; i <= n - 2; i ++) {
int k = upper_bound(a+1, a+1+n, a[i]+u) - a;
--k;
if (k < i+2) continue;
ans = max(ans, (1.0*a[k]-a[i+1])/(1.0*a[k]-a[i]));
}
if (ans == -1) cout << -1 << endl;
else printf("%.9f\n", ans);
}
}


D: 题意有一条河, 有一个人每天都会去看河的高度, 并且会在此时的高度画一条线, 这条线不会消失, 如果某天河的高度与前几天的相同, 那么他就不会画, 因为有已经有线了, 现在告诉你每天可以看到的线的数量, 问sigma(d[i]) 最小是多少, d[i] 定义为第i天在水下的线的数量.

思路: 我们定义t[i] = m[i] + d[i] + 1; 那么要最小化sigma(d[i])等价于最小化sigma(t[i]), 那么很明显我们只知道了m[i], 所以我们可以直接在m[i]上面进行加d[i], 然后问题就变成了在m[i]上如何加最少的d[i]使得t[i] 是非严格递增的数列,并且相邻之差要在1之间?, 所以我们直接贪心的做就好了, 首先从前往后扫, 如果m[i] > m[i+1] , 那么m[i+1] = m[i]; 那么怎么做第二个限制了, 我们就从后往前, 如果m[i] > m[i-1] + 1, 那么m[i-1] = m[i] - 1; 这样做的增量就是最小的sigma(d[i])了.

AC Code

const int maxn = 1e5+5;
int a[maxn];
void solve()
{
int n;
while(~scanf("%d", &n)) {
for (int i = 1 ; i <= n ; i ++) {
scanf("%d", a+i);
}
ll ans = 0;
for (int i = 1 ; i < n ; i ++) {
if (a[i] > a[i+1]) {
ans += a[i] - a[i+1];
a[i+1] = a[i];
}
}
for (int i = n ; i > 1 ; i --) {
if (a[i] > a[i-1] + 1) {
ans += a[i]-1 - a[i-1];
a[i-1] = a[i]-1;
}
}
printf("%lld\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐