打卡信奥刷题(3554)用C++实现信奥题 P11208 『STA - R8』轮回疯狂
2026/9/8 16:10:27 网站建设 项目流程

P11208 『STA - R8』轮回疯狂

题目描述

给一个111nnn的排列ppp,你可以使用两种操作:

  • 轮回:交换ppp中相邻的两个位置。
  • 疯狂:删除ppp中的最小值。如果ppp为空则不能进行操作。

问最少需要多少次操作才能使得序列单调递增。

输入格式

第一行一个正整数nnn

第二行nnn个正整数,描述排列ppp

输出格式

一行一个正整数,表示答案。

输入输出样例 #1

输入 #1

3 3 2 1

输出 #1

2

说明/提示

样例解释:先删除p3p_3p3,再交换p1,p2p_1,p_2p1,p2


本题采用捆绑测试。

数据范围:

  • Subtask 1 (10pts):n≤3n\le 3n3
  • Subtask 2 (30pts):n≤103n\le 10^3n103
  • Subtask 3 (10pts):pi=n−i+1p_i=n-i+1pi=ni+1
  • Subtask 4 (50pts):无特殊限制。

对于全部数据,1≤n≤1051\le n\le 10^51n105ppp111nnn的排列。

C++实现

#include<iostream>usingnamespacestd;constintN=100010;intn;inta[N],pos[N];intinvension[N];structBIT{intc[N];#definelowbit(x)(x&-x)inlinevoidadd(intx,intv){for(;x<=n;x+=lowbit(x))c[x]+=v;}inlineintask(intx){intres=0;for(;x;x-=lowbit(x))res+=c[x];returnres;}}tr1,tr2;//封装数据结构intmain(){scanf("%d",&n);for(inti=1;i<=n;i++){scanf("%d",&a[i]);pos[a[i]]=i;//记录每个数出现在哪个位置}longlongsum=0;for(inti=n;i;i--){invension[i]=tr1.ask(a[i]-1);sum+=invension[i];tr1.add(a[i],1);}longlongans=min(sum,(longlong)n-1);for(inti=1;i<=n;i++)tr2.add(i,1);//一开始每个位置上都有数for(inti=1;i<n;i++){intcnt=tr2.ask(pos[i]-1);sum-=cnt;ans=min(ans,(longlong)sum+i);tr2.add(pos[i],-1);//删掉后这个位置上就没有数了}printf("%lld",ans);return0;}

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询