• 【Educational Codeforces Round 88 (Rated for Div. 2) D】Yet Another Yet Another Task


    题目链接

    点我吧

    题目大意

    给你一个长度为n的序列,先手先选择一个区间[L,R], 这个区间里面的数字, 让后手选择一个删掉。

    然后计算剩余的R-L个数字的和sum(如果R-L等于0,认为和是0)。

    后手总是想让这个sum的值比较低,所以它总是会选择最大的那个数字删掉。

    现在让你帮先手选择一个区间,使得这个区间在被后手删掉一个数字之后, 剩余的和最大。

    题解

    这道题, 如果没有删掉一个数字这个操作的话,就是一个 最大连续和 问题。

    不熟悉这个问题的可以看看我 另外一篇文章

    大家可能都注意到了, a数组中每个元素最大都只是30。

    所以,我们可以先枚举一下最后我们选择的区间里面的最大值ma是多少。

    然后,将原数组做一个改动, 把数组当中所有 大于ma的值全都改成负无穷 (其他的保持不变)。

    然后在这个改动后的数组里面做最大连续子序列问题,因为比ma大的都变成负无穷了,所以肯定最后

    选出来的区间没有大于ma的数字, 这样算出来的 最大连续和减去这个ma 就是最大值为ma的时候,问题的一个可能答案了。

    但是大家可能会觉得,那如果选出来的区间中 没有ma这个数字(里面的数字都比ma小)怎么办? 其实这种情况下,我们因为枚举了

    所有的最大值,所以在 之前的枚举中 肯定会有一次 枚举到 了这个区间的最大值的。

    总结

    挺好的一个思路吧, 枚举矛盾点(最大值)是多少, 因为这个关键的地方被确定了,使得问题被简化(或者说分解成很多个简单的步骤)

    题解

    #include<bits/stdc++.h>
    #define ll long long
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    using namespace std;
    
    const int N = 1e5;
    
    int n;
    int a[N+10];
    
    int main(){
        #ifdef LOCAL_DEFINE
            freopen("D:\rush.txt","r",stdin);
        #endif
        ios::sync_with_stdio(0),cin.tie(0);
        cin >> n;
        rep1(i,1,n){
            cin >> a[i];
        }
        int ans = 0;
        rep1(i,1,30){
            int cur = 0;
            rep1(j,1,n){
                if (a[j]>i){
                    cur = 0;
                }else{
                    cur = cur + a[j];
                    ans = max(ans,cur-i);
                    if (cur<0) cur = 0;
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    geoserver发布mysql表数据
    geoserver1
    geoserver
    快速搭建arcgis以及cesium环境
    openlayers和cesium实现地图二三维切换
    记Mysql类型引起的BUG
    OpenLayers 图层(Layers) 详解
    基于TrueLicense实现产品License验证功能
    第七章
    第六周进度报告
  • 原文地址:https://www.cnblogs.com/AWCXV/p/13053330.html
Copyright © 2020-2023  润新知