Gushing over Programming Girls|

BigSmall_En

园龄:3年2个月粉丝:3关注:5

冒泡排序最外层循环最少所需执行次数计算

给定一个长为 \(n\) 的排列 \(a\),按下列代码执行排序,询问最终 \(ans\) 的值

inline int BF(){
	memcpy(b,a,sizeof(b));
	int ans=0;
	for(int i=1;i<n;++i){
		bool flag=1;
		for(int i=1;i<n;++i){
			if(b[i]>b[i+1]){
				flag=0;
				swap(b[i],b[i+1]);
			}
		}
		if(flag)return ans;
		++ans;
	}
	return ans;
}

解法

将原排列转化为 \(01\) 序列来做

从大到小枚举 \(k \in [1,n]\),新数组 \(b\)\(b_i=(a_i\geq k)\)

找到最小的 \(l\),使得 \(\forall i\in [l,n]\),有 \(b_i=1\),定义 \(x=n-l+1\)(既这串靠右侧 \(1\) 的最长长度)

\(b\)\(1\) 的个数为 \(s\)(容易发现 \(s=n-k+1\)

将这段 \(01\) 序列排序的最外层循环最少执行次数即为 \(s-x\),取所有 \(k\) 的最大值即可

用线段树维护 \(01\) 序列并求得最小的 \(l\),可以做到 \(O(n\log n)\) 的复杂度

还没写证明qwq,可能假了,不过简单对拍了一下没啥问题

丑陋的代码

#include <bits/stdc++.h>

using namespace std;

const int N=500005;
int n,a[N],b[N],loc[N];

int t[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

inline void pushup(int p){t[p]=t[ls]+t[rs];}
void update(int p,int l,int r,int L){
	if(l==L&&r==L){
		++t[p];
		return;
	}
	if(L<=mid)update(ls,l,mid,L);
	else update(rs,mid+1,r,L);
	pushup(p);
}
inline int getans(int p,int l,int r){
	if(l==r){
		if(t[p])return l;
		return 0;
	}
	if(t[rs]==r-mid){
		int x=getans(ls,l,mid);
		if(x)return x;
		return mid+1;
	}
	return getans(rs,mid+1,r);
}

inline int BF(){
	memcpy(b,a,sizeof(b));
	int ans=0;
	for(int i=1;i<n;++i){
		bool flag=1;
		for(int i=1;i<n;++i){
			if(b[i]>b[i+1]){
				flag=0;
				swap(b[i],b[i+1]);
			}
		}
		if(flag)return ans;
		++ans;
	}
	return ans;
}

inline int solve01(){
	int ans=0;
	memset(b,0,sizeof(b));
	memset(t,0,sizeof(t));
	for(int i=1;i<=n;++i)loc[a[i]]=i;
	for(int i=n;i>=1;--i){
		update(1,1,n,loc[i]);
		//printf("update: %d\n",loc[i]);
		int x=getans(1,1,n);
		//printf("%d %d %d\n",i,t[1],x);
		if(x)ans=max(ans,t[1]-(n-x+1));
		else ans=max(ans,t[1]);
	}
	return ans;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)a[i]=i;
	/*for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	printf("%d\n",BF());
	printf("%d\n",solve01());*/
	for(int T=1;T<=1000;++T){
		random_shuffle(a+1,a+1+n);
		/*for(int i=1;i<=n;++i)
			printf("%d ",a[i]);
		printf("\n");*/
		int x=BF(),y=solve01();
		if(x==y)printf("%d YES",T);
		else{
			puts("NO");
			for(int i=1;i<=n;++i)
				printf("%d ",a[i]);
			printf("%d %d\n",x,y);
			break;
		}
	}
	return 0;
}

最后

感谢 Winston12321_ 给我的启发,23级巨佬强得离谱

干打 markdown 没预览,可能写错了很多细节,不管了

本文作者:BigSmall_En

本文链接:https://www.cnblogs.com/BigSmall-En/p/18339383

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   BigSmall_En  阅读(74)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起