iwtgm-5
A.
个数为1的数一定会产生贡献,记为x
个数为2的数一定不会产生贡献,直接全部放入集合a
个数>2的数可产生也可不产生贡献,记为y
分类讨论:
x>0:
x为偶数,那么a,b集合平分x,其他全部放入a集合(反正不会有贡献)
x为奇数,需要多一个y放入b,
x<0,全放入a集合
代码:
int cnt[110];
int a[110];
char c[110];
bool f[110];
map<int,char>mp;
void solve()
{
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
cnt[a[i]]++;
}
int fix=0,change_able=0;
for(int i=1;i<=100;i++){
if(cnt[i]==1)fix++;
else if(cnt[i]==2)continue;
else if(cnt[i]>2)change_able++;
}
if(fix%2==0&&fix!=0){
cout << "YES" << endl;
int p=1;
for(int i=1;i<=n;i++){
if(cnt[a[i]]==1){
if(p&1)c[i]='A';
else c[i]='B';
p++;
}
}
for(int i=1;i<=n;i++){
if(c[i]=='B')cout<<'B';
else cout<<'A';
}
} else if(fix%2!=0&&fix!=0&&change_able){
cout << "YES" << endl;
int p=1;
for(int i=1;i<=n;i++){
if(cnt[a[i]]==1){
if(p&1)c[i]='A';
else c[i]='B';
p++;
}
}
for(int i=1;i<=n;i++){
if(cnt[a[i]]>2){
c[i]='B';break;
}
}
for(int i=1;i<=n;i++){
if(c[i]=='B')cout<<'B';
else cout<<'A';
}
} else if(fix==0) {
cout << "YES" << endl;
for(int i=1;i<=n;i++)cout<<'A';
}else cout<<"NO";
}
C.
先考虑如何求最大连续子序列和
int n;
int a[N],dp[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int ans=0;
for(int i=1;i<=n;i++){
dp[i]=max(a[i],dp[i-1]+a[i]);//dp[i]表示当前数一定要取(要么自己是头,要么接在上一个后面)
ans=max(ans,dp[i]);//有可能不要当前数是最优,所以要每次取最大值
}
cout<<ans;
}
dp[i][]表示一定要取当前数
现在是加了状态,
3种:
dp[i][0]表示到目前是还没用魔法的,当前数无魔法
dp[i][1]表示到目前正在用魔法,当前数有魔法
dp[i][2]表示魔法已经用完了,当前数无魔法
int n;
ll x;
ll a[N],dp[N][3];
void solve()
{
cin>>n>>x;
for(int i=1;i<=n;i++)cin>>a[i];
ll ans=0;
for(int i=1;i<=n;i++){
dp[i][0]=max({a[i],dp[i-1][0]+a[i]});//自己是头或者接到前面
dp[i][1]=max({dp[i-1][0]+a[i]*x,dp[i-1][1]+a[i]*x,a[i]*x});//前一个数没用魔法或者用魔法加上当前数用魔法,或者自己用魔法当头
dp[i][2]=max({dp[i-1][1]+a[i],dp[i-1][2]+a[i],a[i]});//前一个数用魔法或用完魔法加上当前数,或者自己当头
ans=max({ans,dp[i][0],dp[i][1],dp[i][2]});//同样有可能不要当前数更优,每次都要比较
}
cout<<ans;
}
更简便的:
int n;
ll x;
ll a[N],dp[N][5];//dp[i][]表示一定要取当前数
void solve()
{
cin>>n>>x;
for(int i=1;i<=n;i++)cin>>a[i];
ll ans=0;
for(int i=1;i<=n;i++){
dp[i][0]=max(dp[i-1][0]+a[i],0ll);//因为子序列可以为空,所以当前数是负数的话直接置0更优,和接到前面比较(前面>=0)
dp[i][1]=max(dp[i][0],dp[i-1][1]+a[i]*x);//此时dp[i][1]和dp[i][0]比较,只有dp[i-1][1]是因为上一次的dp[i][1]和dp[i][0]已经比过了,也就是说此时的dp[i-1][1]中的数是上一次的dp[i][1]和dp[i][0]的较大值
dp[i][2]=max(dp[i][1],dp[i-1][2]+a[i]);//同上理
ans=max(ans,dp[i][2]);//同样可能不取当前数会更优,所以每次都要比较
}
cout<<ans;
}