atcode E - guruguru(思维+前缀)

题目链接:http://arc077.contest.atcoder.jp/tasks/arc077_c

 

题解:一道思维题。不容易想到类似区间求和具体看一下代码。

#include <iostream>
#include <cstring>
#include <cstdio>
#define inf 0X3f3f3f3f
using namespace std;
const int M = 1e5 + 10;
typedef long long ll;
int a[M];
ll add[M] , del[M];//add[i]表示取大于i的数为x时所需要的价值最小是多少,当然add是要结合del的del是类似于遍历i之后的数
int main() {
    int n , m;
    scanf("%d%d" , &n , &m);
    for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i]);
    for(int i = 1 ; i < n ; i++) {
        int x = a[i] , y = a[i + 1];
        if(x < y) {
            add[1] += (y - x);
            add[x + 1] -= (y - x);
            del[x + 1]--;
            add[y + 1] += (y - x);
            add[x + 1] += y + 1;
            del[y + 1]++;
            add[y + 1] -= y + 1;
        }
        else if(x > y) {
            add[1] += y + 1;
            del[1]--;
            add[y + 1] -= y + 1;
            add[y + 1] += m - x + y;
            del[y + 1]++;
            add[x + 1] -= m - x + y;
            add[x + 1] += y + 1 + m;
            del[x + 1]--;
        }
        //这些处理都是可以想到的。就是在3个范围内(1~x,x~y,y~m)or(1~y,y~x,x~m)注意前一个区间加上去之后下个区间要减去。由于还与区间中取什么数有关所以引入了del
    }
    add[0] = 0 , del[0] = 0;
    for(int i = 1 ; i <= m ; i++) {
        add[i] += add[i - 1];
        del[i] += del[i - 1];
        //这种区间求和也可以利用这种方法来处理,或者使用其他数据结构的知识
    }
    ll ans = 1e12;
    for(int i = 1 ; i <= m ; i++) {
        ans = min(ans , add[i] + (ll)i * del[i]);
    }
    printf("%lld\n" , ans);
    return 0;
}

转载于:https://www.cnblogs.com/TnT2333333/p/7105861.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值