给定一个长为 \(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 没预览,可能写错了很多细节,不管了
标签:外层,01,return,int,冒泡排序,flag,最少,ans,sizeof From: https://www.cnblogs.com/BigSmall-En/p/18339383