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; };
算补完全部了,结束

浙公网安备 33010602011771号