题解:P14258 好感(favor)
VinstaG173 · · 题解
tag:贪心。
暴力
浮板只有
贪心策略
首先确定最终要变成正面或者反面,不妨设为正面,实现时求出两种情况答案再取
将浮板
如果有正面朝上的浮板被翻过面,不妨设其中被翻面时下标最小的一个当时为浮板
重复以上调整,可以得知只将反面浮板翻面,对于不需要翻面的浮板则从不翻面,能够达到最优答案。此时每个浮板至多翻面一次,同上分析得每次翻面对最终总移动距离的增加至少为
如果某一次将
显然此时我们可以贪心地每次选取最大的
直接模拟上述翻面过程可以做到
Code:
int m;
int p[1000003];
inline ll calc(){
ll res=0;
for(int i=m;i>0&&p[i]>=1;--i){
res+=p[i];
for(int j=i-1;j>0&&p[j]>=1;--j){
if(p[j]==1)++res;
--p[j];
}
}return res;
}
int n;
ll rs0,rs1;
char s[1000003];
inline void solve(){
cin>>n>>s+1;m=0;
for(int i=1;i<=n;++i)
if(s[i]=='0')p[++m]=i;
rs0=calc();m=0;
for(int i=1;i<=n;++i)
if(s[i]=='1')p[++m]=i;
rs1=calc();cout<<min(rs0,rs1)<<"\n";
}
特殊性质
其实是为了多给点部分分。可以直接计算将前
正解
事实上由上面得出的移动距离公式可以
具体实现中可以记录一个变量
总时间复杂度 long long。
Code:
int m;
int p[1000003];
inline ll calc(){
ll res=0;
for(int i=1,j=m,c=0;j>=i;){
res+=p[j]-c;++c;--j;
if(i<=j&&p[i]==c)++res,++i;
}return res;
}