codeforces 1067 div.2

B

从样例中观察到,k为偶数的时候总是第一个人拿掉一个第二个人也拿掉他,所以无效

当k为奇数的时候,就是查找两个数列a,b中可以吧a中一个元素替换为ai+bi的最大子段和

    vector<int>a(n),b(n);
    for(auto &it:a)cin>>it;
    vector<int>dp(n+1,-INT_MAX);
    int ans=-LLONG_MAX;
    for(int i=1;i<=n;i++){
        dp[i]=max(dp[i-1]+a[i-1],a[i-1]);
        ans=max(ans,dp[i]);
    }

 

这个就是最大字段和的dp

但是如果要选择一个位置i,让ai变为bi,这样的最大字段和呢?思考了一段时间发现dp思路不难

我们保留dp数组为原始数组

新建一个f数组作为操作一次之后的维护数组

fi代表到当前位置进行一次操作后包含位置i的最大字段和

fi是由三部分来的max(之前没进行操作这一次进行操作(包含常规dpi-1,和从i新开始),之前进行操作过而这一次不进行操作)

这样遍历一下就可以得到答案

vector<int>f(n+1,-INT_MAX);
for(int i=1;i<=n;i++){
      f[i]=max(f[i-1]+a[i-1],dp[i-1]+b[i-1]+a[i-1]);
      f[i]=max(f[i],b[i-1]+a[i-1]);
      ans=max(ans,f[i]);
}

  D(待补题)

很简单可以考虑到要把这里两个字符串弄到同一种形式然后再反转T->MID

一开始没有想到如何反转这个字符串到达一个统一的形式,看答案发现可以一直调整字符的前三个因为如果没有两个11,00就一定存在101010这种类型,

所以一直反转就可以把字符规整到00000 这种全零类型

一开始以为是N=1e5没考虑到n^2做法,这个题作为第D题思维深度小多了,就是比较难猜到

auto exto=[&](string a){
        vector<pii>res;
        int len=a.size();
        while(1){
            int f=1;
            for(auto it:a)
                if(it=='1'){f=0;break;}
            if(f)break;
            int l=0,r=2;
            for(int i=0;i<len;i++){
                if(a[i]==a[i+1]){
                    l=i,r=i;
                    for(int j=i;j<len;j++){
                        if(a[j]==a[j+1])r++;
                        else break;
                    }
                    break;
                }
            }
            for(int i=l;i<=r;i++)
                a[i]=!(a[i]-'0')+'0';
            res.push_back({l+1,r+1});
        }
        return res;
    };

算补完全部了,结束

posted @ 2025-12-01 17:29  zhzhzhao  阅读(1)  评论(0)    收藏  举报