北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛 A题题解

蹦!蹦!蹦!

https://ac.nowcoder.com/acm/contest/16323/A

瞎bb

这题在现场想到了贪心部分,也想到了优化要用到线段树/树状数组。时间不太够我
码了,就直接放弃思考了,现在看来当时想的思路是正确的,码一下树状数组说不定
能过2。赛后补题,思路代码几乎都对了,然后一个小细节给我绕进去了,卡了半
天,好歹最后和lzh讨论了一下,改了一个参数过了233,标程是差分数组,我采用了
线段树的做法。

题解

前置知识:树状数组,差分

贪心部分

1.从左开始遍历,遍历到第一个大于1(即需要跳跃的蹦床)则在这个蹦床开始跳一定是
最优解
证明:设开始跳的蹦床为第i个,左侧的所有蹦床都为1,右侧的未知,从右侧任何一个
蹦床开始跳跃都无法对第i个蹦床产生贡献,左侧的任何一个蹦床开始跳,最终都会达到
第i个蹦床,且费用一定是1,因此从第i个蹦床开始跳跃一定为最优解(当然从左侧第一
个开始跳也最优解,不过这样难以实现)

2.计a[i]为原第i个蹦床的弹力值,c[i]为从左侧跳到第i个蹦床的次数。
情况1:如果a[i]>1,则一定从a[i]个蹦床往后跳a[i]-1次,且对[i+2,i+a[i]]的蹦床产生一个1的贡献,
情况2:如果a[i]-c[i]<1,则表示i蹦床弹力值到1后仍进行了c[i]-a[i]-1次跳跃,且这些贡献只会出现在c[i+1]中(这里卡了我好久,把自己绕进了对[i+1,n]产生贡献里)。
情况3:只有遍历到i个蹦床且a[i]-c[i]>1时才需要选择i为起点进行跳跃。

数据结构部分

理解了上述贪心部分数据结构部分则很简单了,问题已经抽象为区间修改和单点查询。用
树状数组或者线段树直接莽过去(线段树赛后补题实测会t,比赛时提交是否能ac不清楚)。

代码

#include<stdio.h>
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;

//a数组是原数组,c是树状数组。
int kase , n , a[5100] , c[5100];
inline int lowbit(int x){
    return x & (-x);
}
void add(int pos , int x){
    while (pos <= n) c[pos] += x , pos += lowbit(pos);
}
int query(int pos){
    int res = 0;
    while (pos > 0) res += c[pos] , pos -= lowbit(pos);
    return res;
}

int main() {
    scanf("%d", &kase);
    while (kase--) {
        memset(a, 0, sizeof a);
        memset(c, 0, sizeof c);
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        ll res = 0;
        for (int i = 1; i <= n; i++) {
            int tmp = query(i);
            if (a[i] - tmp > 1) {
                //情况3
                res += a[i] - tmp - 1;
            } else if (a[i] - tmp < 1) {
                //情况2
                add(i + 1, -(a[i] - tmp) + 1);
                add(i + 2, -(-(a[i] - tmp) + 1));
            }
            if (a[i] > 1) {
                //情况1
                add(i + 2, 1);
                add(min(i + a[i] + 1, n + 1), -1);
            }
        }
        printf("%lld\n", res);
    }
}
全部评论

相关推荐

比亚迪汽车新技术研究院 硬件工程师 总包21左右 硕士
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务