题目出处:
「EZEC-10」排列排序 - 洛谷
题目内容:
小 E 给你一个长度为 nnn 的排列 p1,p2,⋯ ,pn 。小 E 想要把它排序。
小 E 每次可以花区间长度,即 r−l+1 的代价,选择排列中的任意一段区间 [l,r],并将 [l,r] 从小到大排序。
现在你可以让他进行若干次这个操作,直到 p 中元素的值从 1 到 n 按升序排序,即对于 1 到 n 的每一个 i,都有 pi=i 。
小 E 问你,他花的代价最少为多少?
输入格式
本题有多组询问,第一行有一个数 T 表示询问组数。
对于每组询问:
第一行给出一个整数 n。
第二行 n 个整数,由空格隔开,代表排列 p 中元素的值。
输出格式
T 行,每行一个整数表示一组询问的答案。
输入
2
3
1 3 2
4
3 2 1 4
输出
2
3
数据规模与约定
【样例 1 说明】
对于第一组数据,可选择区间 [2,3] 进行排序。
对于第二组数据,可选择区间 [1,3] 进行排序。
数据保证,1 <= T, ∑n <= 10^6。
思路:双指针
双指针,做指针设为l,右指针设为 r,l 从1循环到 n,通过下标是否与值相等确定数是否在正确的位置:正确则 l++ 进入下一循环;否则,判断当前 l 所在的循环里第 l 个数的值是否大于右端 r ,如果大于则扩大右端 r 的范围,通过设的 tem 维护,第 r 个与下一个(第 r+1 )中最大的保留(如果还没找到最大的 tem 的对应位置),使循环让所有 l 到新的 r 都能排好队,且下一个正常,也即该段成功排好序列,得出排好该序列的代价 minr ,minr累加到最后得到总的代价。
AC代码
#include<bits/stdc++.h>
using namespace std;
int num[1000005];
int main()
{
int t,i,j; cin>>t;
while(t--)
{
int n,l,r,minr=0,tem=0; cin>>n;
for(i=1;i<=n;i++) cin>>num[i];
for(l=1;l<=n;)
{
if(num[l]==l) l++;
else
{
tem=num[l];
r=l+1;
tem=max(tem,num[r]);
while(tem>r)
{
r++;
tem=max(tem,num[r]);
}
minr+=r-l+1;
l=r+1;
}
}
cout<<minr<<endl;
}
return 0;
}
谢谢。😘