题解:CF2025D Attribute Checks
Misaka屮Mikoto · · 题解
CF2025D Attribute Checks
题目大意
给定两个正整数
你有两个初始值均为
-
如果
r_i > 0 并且此时I \ge |r_i| ,则你获得一分。 -
如果
r_i < 0 并且此时S \ge |r_i| ,则你获得一分。 -
如果
r_i = 0 ,则你需要从以下两种决策中选择一种:将I 的值增加1 ,或者将S 的值增加1 。
求你最终能获得分数的最大值。
数据范围
时空限制
- 2.5 seconds
- 512 megabytes
思路
注意到这里
m 的范围和时间限制,明显可以考虑O(m^2) 时间复杂度的算法。
我们发现,只有当
每一次决策我们可以从
我们将
对于获得每一次决策后,这个“决策数”后面每一个数字的数量
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int pot1[5010][5010],pot0[5010][5010];int n,m,cnt;
//pot1[i][j]代表第m-i次决策的r后面大于0的数字j 的个数
//pot1[i][j]代表第m-i次决策的r后面小于0的数字,绝对值j 的个数
ll dp[5010][5010];
int main(){
//freopen("read.in","r",stdin);
stack<ll>st;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
ll l;
scanf("%lld",&l);
st.push(l);
}
while(!st.empty()){
int l=st.top();
st.pop();
if(l==0){
cnt++;
for(int i=0;i<=m;++i)pot1[cnt][i]=pot1[cnt-1][i],pot0[cnt][i]=pot0[cnt-1][i];
}
if(l<0)pot0[cnt][-l]++;
if(l>0)pot1[cnt][l]++;
}
for(int i=1;i<=m;++i){
for(int j=0;j<=m;++j){
if(j-1>=0)dp[j][i-j]=max(dp[j][i-j],dp[j-1][i-j]+pot0[m-i][j]);
if(i-j-1>=0)dp[j][i-j]=max(dp[j][i-j],dp[j][i-j-1]+pot1[m-i][i-j]);
}
}
ll mxn=0;
for(int i=0;i<=m;++i)mxn=max(mxn,dp[i][m-i]);
printf("%lld",mxn);
}