题解 P6447 [COCI2010-2011#1] ŽABE
洛谷。
题意
一共有
每次操作,可以使编号为
(比较想知道为什么我们的翻译是青蛙)。
分析
这是一道构造题,我们需要使两个序列相近。
令原序列为
对于这个
我们在使序列接近我们的
每次,我们使两个
不妨令
- 使
移动到 的左侧。 - 使
到 中间的数都移动开。
对于第一种,我们可以在模拟的过程中发现,我们移动
也就是说,我们移动
这也就使得,我们这种移动方式可能不能仅靠移动
对于第二种,我们贪心上可以从小到大移动这些数,是这些数移出这个区间内。
这时我们发现,我们的
稍微证明一下,假如我们的另一个区间的之间长度为
然后我们就可以使我们的区间不断移动出这个区间了。
于是,我们就可以解决了从
而我们从
inline int find(int a[],int x) { for(int i=1; i<=n; ++i) if(a[i]==x) return i; } inline bool check(int L,int R,int x) { if(L<R) return L<x&&x<R; else return x<R||L<x; } inline void solve(int a[],int to[],bool flag) { top=0; for(int i=n-1; i; --i) { while(1) { int L=find(a,i); int R=find(a,i+1); if(L%n+1==R) break; int idx=L%n+1; for(int j=L%n+1; j!=R; j=j%n+1) if(a[j]<a[idx]) idx=j; R=find(a,n); while(check(L,R,idx)) { ans[++top]=a[idx]; int cnt=a[idx]; while(cnt--) { swap(a[idx],a[to[idx]]); if(a[idx]==n) R=idx; else if(a[idx]==i) L=idx; idx=to[idx]; } } } } if(!flag) for(int i=1; i<=top; ++i) cout<<ans[i]<<"\n"; else for(int i=top; i; --i) cout<<ans[i]<<"\n"; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!