YACS-2024年4月-乙组-T1

题目

题目描述

给定一个只由 01 构成序列,不断扫描序列,在每一轮扫描的过程中,如果发现有一些 10 相邻,且 1 在前,0 在后,就在这一轮扫描后,同时将这些 1 与相邻的 0 交换。不断进行调整直到将所有的 0 都在序列的前一半,所有的 1 都在序列的后一半为止。
请计算需要进行多少轮交换才能完成调整。

输入

若干 01 字符组成的一个序列

输出

单个整数:表示交换的次数。

数据范围

1 序列的长度 300,000

样例数据
输入: 1100
输出: 3

赛时代码 (60p40pTLE)

#include<bits/stdc++.h>
using namespace std;
int main()
{
	string s;
	bool flag=0;
	int cnt=0;
	cin>>s;
	while(!flag) 
	{
		bool f=1,pos[300005]={};
		for(int i=1;i<s.size();i++)
		{
			if(s[i-1]=='1'&&s[i]=='0')
			{
				pos[i]=true;
				f=0;
			}
		}
		for(int i=1;i<s.size();i++)
		{
			if(pos[i]==1)
			{
				s[i]='1';
				s[i-1]='0';
			}
		}
		if(!f) cnt++;
		else flag=1;
	}
	cout<<cnt;
	return 0;
}

正解思路:

该题其实是逆序对数的一个特殊情况。对每个 si=1,其交换次数就是 i 右侧 0的个数(不妨记为 ci),则
ans=si=1ci

本题中考虑每一轮是并行的,粗略看答案大概是 max1...nci
⁡这种形式。但关键是会出现 11 这种情况,导致左边的 1 不得不若干轮,而等的情况可能是级联产生的,具体过程可能很复杂,如 10111011。所以不能往这个方向去想,而应该抓住一些整体的量

对某个 si=1,记 nxtii 右侧第一个 1 的位置(如没有则为 n+1),也就是可能挡住 si 右移的位置。wtisi 总共空等的轮数。则显然 maxsi=1{ci+wti}
这样,关键就变成求 wt[i],这里分几种情形

1o nxti=i+1wtnxti=0
i等一轮后就不会再空等,wti=1

2o nxti=i+1wtnxti>0
一旦 nxti 等一轮,i 随之也会(在下一轮)等一轮,故 wti=wtnxti+1

3o nxti=i+1
则之间有若干个 0,每个 0 可以帮 i 至多节省一轮时间,当然 wti 也不可能为负,故 wti=max(0,wtnxti+1(nxtii1))

4o ci=0
这时候 i 根本不用移,则直接 wti=0

正解代码:

#include<bits/stdc++.h>
using namespace std;
string s;
long long n,wt[300005],nxt[300005],ans;
int main() 
{
    cin>>s;
    n=s.length();
    for(long long i=n,k=n+1,cnt=0;i>=1;i--)
    {
        if(s[i-1]=='0') cnt++;
        else
        {
            nxt[i]=k; 
            k=i;
            wt[i]=max((long long)0,wt[nxt[i]]+1-(nxt[i]-i-1));
            if(cnt) ans=max(ans,cnt+wt[i]);
        }
    }
    cout<<ans;
    return 0;
}
posted @   XLoffy  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示