关于排序
update 2.16
一个晚自修的想法
对一个序列
如:
计算其“上坡”(上升序列),记录每个“上坡”的起始位置
如:
记录起始位置为:
同理,记录“下坡”
比较
对每两个相邻的“上坡”做一次merge
操作,变化过程为:
同理,若
设“上坡”个数为
P1177实测代码
#include<cstdio>
int n;
int a[200000];
int up[200000];
int down[200000];
int uptot,downtot;
int now;
inline void merge(int l,int mid,int r,int type)
{
int i=l,j=mid+1,k=l;
int b[200000];
while(i<=mid&&j<=r)
{
if(type==1)//up
{
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
else//down
{
if(a[i]>a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(i=l;i<=r;i++) a[i]=b[i];
}
inline void swap(int &x,int &y)
{
int tmp=x;
x=y;
y=tmp;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
now=a[1];
up[++uptot]=down[++downtot]=1;
for(int i=1;i<=n;i++)
{
if(a[i]<now) up[++uptot]=i;
if(a[i]>now) down[++downtot]=i;
now=a[i];
}
up[++uptot]=down[++downtot]=n+1;
if(uptot<downtot)
for(int i=1,j=2;j<uptot;j++) merge(up[i],up[j]-1,up[j+1]-1,1);
else
{
for(int i=1,j=2;j<downtot;j++) merge(down[i],down[j]-1,down[j+1]-1,2);
for(int i=1,j=n;i<j;i++,j--) swap(a[i],a[j]);
}
for(int i=1;i<=n;i++) printf("%d ",a[i]);
return 0;
}
在最坏情况下,应该是
#2会TLE,求优化方案
(什么LaTeX,不改成代码块都会变成一级标题)
update 2.18(偷偷用教室的电脑打的)
发现之前的搞错了,并不能比较数组长度
hack data:
1 2 3 4 5 6 7 8 7 6 5 4 3 2
显然,
升序需赋值:
降序需赋值:
故应:
若
则以升序排序
否则以降序排序
其中:
#include<cstdio>
int n;
int a[200000];
int up[200000];
int down[200000];
int P[200000];
int Q[200000];
int sump,sumq;
int uptot,downtot;
int now;
inline void merge(int l,int mid,int r,int type)
{
int i=l,j=mid+1,k=l;
int b[200000];
while(i<=mid&&j<=r)
{
if(type==1)//up
{
if(a[i]<a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
else//down
{
if(a[i]>a[j]) b[k++]=a[i++];
else b[k++]=a[j++];
}
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(i=l;i<=r;i++) a[i]=b[i];
}
inline void swap(int &x,int &y)
{
int tmp=x;
x=y;
y=tmp;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
now=a[1];
up[++uptot]=down[++downtot]=1;
for(int i=1;i<=n;i++)
{
if(a[i]<now) up[++uptot]=i;
if(a[i]>now) down[++downtot]=i;
now=a[i];
}
up[++uptot]=down[++downtot]=n+1;
for(int i=1;i<uptot;i++)
{
P[i]=up[i+1]-up[i];
sump+=(uptot-i)*P[i];
}
for(int i=1;i<downtot;i++)
{
Q[i]=down[i+1]-down[i];
sumq+=(downtot-i)*Q[i];
}
if(sump<=sumq)
for(int i=1,j=2;j<uptot;j++) merge(up[i],up[j]-1,up[j+1]-1,1);
else
{
for(int i=1,j=2;j<downtot;j++) merge(down[i],down[j]-1,down[j+1]-1,2);
for(int i=1,j=n;i<j;i++,j--) swap(a[i],a[j]);
}
for(int i=1;i<=n;i++) printf("%d ",a[i]);
return 0;
}
时间复杂度为玄学(?)
然而TLE了更多(?,指#2和#4)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构