P8847 [JRKSJ R5] 1-1 A 题解
P8847 [JRKSJ R5] 1-1 A
普通思路:枚举所有可能,然后每次求出最大子段和。可通过
如果想要AC,时间复杂度就需要控制在
注意此题有一个特殊性质:
根据本题的特殊性,我们可以分类讨论以下三种情况:
这时我们就可以把
然后将多余的
- 根据贪心策略,最后多余的
-1 一定不会选。 - 只选择一个数时,选择一个
1 为最优。 - 选择多个数时,由于
-1 和1 相邻,所以相邻的两数会互相抵消,导致最后不会剩下数或者只会剩下一个数,其实相当于是选择一个数的情况。
所以这种方法最大子段和为
可以证明,只要数列中有
这种情况类似于上面的情况,也是将
仍然将
这种排列的最大子段和为
证明:由于可以选择整个序列,所以无论怎么重排,最大子段和必然不小于
至于为什么要把
AC Code:
#include<bits/stdc++.h>
using namespace std;
int a,v1,v2;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a;
if(a==1)
v1++;
else
v2++;
}
if(v2==v1)
{
for(int i=1;i<=n;i++)
{
if(i%2)
cout<<1<<" ";
else
cout<<-1<<" ";
}
}
else if(v2>v1)
{
for(int i=1;i<=v1*2;i++)
{
if(i%2)
cout<<1<<" ";
else
cout<<-1<<" ";
}
for(int i=1;i<=n-v1*2;i++)
cout<<-1<<" ";
}
else
{
for(int i=1;i<=v2*2;i++)
{
if(i%2)
cout<<1<<" ";
else
cout<<-1<<" ";
}
for(int i=1;i<=n-v2*2;i++)
cout<<1<<" ";
}
return 0;
}
时间复杂度: