• abc 137 Count 1‘s 【经典思维】


    给定一串1、0数字,可以选择任意区间翻转,0会变成1,1会变成0。问区间的取值种类有多少。

    思维:

    这个题也是匹配问题,因为 0 1 是相消的, 怎么体现相消呢,一个置1,一个置-1呗。再继续思考,对于每个区间如果数 > 0 意味着1多,翻过来总体的值就变小,< 0 意味着0多,反过来总体的值就变大。找区间的最大最小值。

    再数学化一点:

    假设 a 是一个原串的 1 的数量,b 是选择的区间的 0 的数量,c 是选择的区间的 1 的数量,则翻转后串的价值是 a+b-c
    a 的数量是确定的,变的是 b-c 的数量,所以我们只需要知道 b-c 的值可能有多少种即可。所以考虑将字符 1 的位置看做数值 1,将字符 0 的位置看做数值-1这样使得区间数字和就是 b-c。

    现在问题变成给定一个数组,问区间和存在多少种不同的值
    由于数值只有 1 和-1,所以我们可以求最大区间子段和与最小区间
    子段和的差值即可

    码风一:能加就加原则,不能加就赋值

    1. for (int i = 0; i < n; i ++ ) {
    2. if(sum < 0) sum = a[i];
    3. else sum += a[i];
    4. mx = max(mx, sum);
    5. }

    码风二:tourist的思维,R(答案上界,一定是由某一个pref减去他前面的最小值),L(答案下界),    mx(维护的是当前i之前的所有的最小值),mi。 注意,这套“模板”mx和mi的更新是在r和l之后的。

    1. #include
    2. typedef long long ll;
    3. using namespace std;
    4. int main(){
    5. //std::ios::sync_with_stdio(false);
    6. //std::cin.tie(nullptr);
    7. int n;
    8. cin >> n;
    9. std::vector<int> a(n);
    10. for (int i = 0; i < n; i ++ ) {
    11. cin >> a[i];
    12. a[i] = (a[i] == 1 ? 1 : -1);
    13. }
    14. vector<int> pref(n + 1, 0);
    15. for (int i = 0; i < n; i ++ ) {
    16. pref[i + 1] = pref[i] + a[i];
    17. }
    18. int L = 0;
    19. int R = 0;
    20. int mi = 0;
    21. int mx = 0;
    22. for (int i = 1; i <= n; i ++ )
    23. {
    24. R = max(R, pref[i] - mi);
    25. L = min(L, pref[i] - mx);
    26. mx = max(mx, pref[i]);
    27. mi = min(mi, pref[i]);
    28. }
    29. cout << R - L + 1 << '\n';
    30. return 0;
    31. }

    再数学化一点:

    假设 a 是一个原串的 1 的数量,b 是选择的区间的 0 的数量,c 是选择的区间的 1 的数量,则翻转后串的价值是 a+b-c
    a 的数量是确定的,变的是 b-c 的数量,所以我们只需要知道 b-c 的值可能有多少种即可。所以考虑将字符 1 的位置看做数值 1,将字符 0 的位置看做数值-1这样使得区间数字和就是 b-c。

    现在问题变成给定一个数组,问区间和存在多少种不同的值
    由于数值只有 1 和-1,所以我们可以求最大区间子段和与最小区间
    子段和的差值即可

    再数学化一点:

    假设 a 是一个原串的 1 的数量,b 是选择的区间的 0 的数量,c 是选择的区间的 1 的数量,则翻转后串的价值是 a+b-c
    a 的数量是确定的,变的是 b-c 的数量,所以我们只需要知道 b-c 的值可能有多少种即可。所以考虑将字符 1 的位置看做数值 1,将字符 0 的位置看做数值-1这样使得区间数字和就是 b-c。

    现在问题变成给定一个数组,问区间和存在多少种不同的值
    由于数值只有 1 和-1,所以我们可以求最大区间子段和与最小区间
    子段和的差值即可

  • 相关阅读:
    『现学现忘』Git基础 — 12、Git用户签名的其他操作
    linux写代码环境和工具
    《算法通关村第二关黄金挑战一一K个一组反转》
    npm更换成淘宝镜像源及cnpm使用
    忘记密码,如何解除Excel的限制保护?
    MyBatisPlus入门
    HCIA11 网络安全之本地 AAA 配置实验
    人工智能数学课高等数学线性微积分数学教程笔记(5. 线性代数高级)
    【数据分享】2020年全国90个城市市域范围的建筑体块数据(shp格式/超2亿栋建筑)
    科技改变视听4K 120HZ高刷新率的投影、电视、电影终有用武之地
  • 原文地址:https://blog.csdn.net/IsayIwant/article/details/126592348