zoukankan      html  css  js  c++  java
  • 增减序列

     

     贪心加差分,不愧是拔高的题目,好题

    主要有一点不好理解,为什么最终所有可能的序列是abs(pos - neg) + 1种

    pos和neg中的小者就是b[i]和b[j]一正一负配对时+1-1操作的数量
    剩余的|pos-neg|就是落单的差分序列中的正数或负数b[k],这些差分序列剩余的正数或负数b[k]可以通过与差分序列

    中b[1]或b[n+1]进行+1-1操作使b[k]逐步变到0,而这些b[k]如果与b[1]配对进行+1-1的操作则会影响常数列的初值a[1],

    从而影响最终的常数列。所以常数列的最多可能有|p-q|+1种(算上前面min(neg,pos)次不影响常数列初值的操作),最少可能有

    1种,就是差分序列中剩余的b[k]都与b[n+1]配对进行+1-1的操作,也就是一次也不和b[1]配对

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 100010;
     5 int a[N];
     6 int main() {
     7     int n;
     8     cin >> n;
     9     for (int i = 1; i <= n; i++) { //读入原数组
    10         cin >> a[i];
    11     }
    12     for (int i = n; i > 1; i--) { //把a数组变为它自己的差分数组
    13         a[i] -= a[i - 1];
    14     }
    15     ll pos = 0; //存储所有正数的和
    16     ll neg = 0; //存储所有负数的和
    17     for (int i = 2; i <= n; i++) {
    18         if (a[i] > 0) {
    19             pos += a[i];
    20         } else {
    21             neg -= a[i]; //注意此时的a[i]是负数,所以此处是减等。如果写加等,最后需要neg=abs(neg)
    22         }
    23     }
    24     //neg = abs(neg); //若上面写+=,此处需要取消注释
    25     cout << min(pos, neg) + abs(pos - neg) << endl; //操作次数
    26     cout << abs(pos - neg) + 1 << endl; //方案数
    27     return 0;
    28 }
  • 相关阅读:
    [网络] 第五章 运输层
    pubwin
    R语言
    我的微博开通啦
    迅雷使用积分制的真正作用和目的 [揭密迅雷]
    求数组里面第二大的数
    xp环境下安装vmware workstation 7出错
    一道大学c语言作业题
    写在断网的那些日子里
    mysql里奇怪的日期201627 14:28:15
  • 原文地址:https://www.cnblogs.com/fx1998/p/13924720.html
Copyright © 2011-2022 走看看