• GJGHFD的排列 题解 [DP]


    GJGHFD的排列

    Description:

    ​ 给定一个长度为 (n) 的排列 (p_1), (p_2), · · · , (p_n),你可以做以下两个操作之一:

    ​ 1.将 (p_{n−1}) 移到 (p_1) 之前,即 (p_1), (p_2), · · · , (p_n) ( ightarrow) (p_{n−1}), (p_1), (p_2), · · · , (p_{n−2}), (p_n).

    ​ 2.将 (p_{1}) 移到 (p_n) 之后,即 (p_1), (p_2), · · · , (p_n) ( ightarrow) (p_2), (p_3), · · · ,(p_{n−1}), (p_n), (p_{1}).

    ​ 一串连续的 (1) 操作称为一次 (3) 操作. 求使得原排列变为 (1, 2, · · · , n) 的操作序列中包含的 (3) 操作的最小次数.

    Input:

    ​ 第一行一个整数 (n),表示排列长度.
    ​ 接下来一行 (n) 个整数,给出这个排列.

    Output:

    ​ 一行一个整数表示答案.

    Sample Input:

    6
    2 4 5 1 3 6
    

    Sample Output:

    2
    

    样例解释:

    ​ 首先做 (5)(2) 操作,原排列变为 (6, 2, 4, 5, 1, 3);
    ​ 再做 (3)(1) 操作,原排列变为 (4, 5, 1, 6, 2, 3);
    ​ 再做 (4)(2) 操作,原排列变为 (2, 3, 4, 5, 1, 6);
    ​ 最后做 (3)(1) 操作,原排列变为 (1, 2, 3, 4, 5, 6) .

    Hint:

    ​ 对于(100\%)的数据,(1 leq n leq 500)

    ​ 时间限制: (1s)

    ​ 空间限制: (512M)

    题目分析:

    ​ 我们经过手玩一下操作 (3) ,可以发现其实操作 (3) 的效果等价于把序列中任意元素取出来,扔到序列中的任意位置(我们可以通过 (2) 操作调整)。再思考一下,我们枚举每一个序列中每一个位置作为起点,其实就是求最长上升子序列的长度最大值 (L) ,然后答案就是 (n-L).(因为考虑操作 (3) 的效果就是把无序的元素变得有序,那我们找出最长的有序序列,那么剩下的就是需要调整的,我们要使调整次数最少,就让这个最长上升子序列最长)

    ​ 那么这里采用的方法是树状数组优化DP,单调栈也可以。

    ​ 代码如下(马蜂很丑,不喜勿喷)——

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define Tp template<typename T>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define maxn 1005
    #define LL long long
    using namespace std;
    int n,ans=maxn,pos[maxn],maxx[maxn],p[maxn];
    inline void add(int x,int y){for(register int i=x;i<=n;i+=i&-i) maxx[i]=max(maxx[i],y);}
    inline int ask(int x){int res=0;for(register int i=x;i;i-=i&-i) res=max(res,maxx[i]);return res;}
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))
    		char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[25];
    	public:
    		FileInputOutput(void) { Ftop=Fout; Fend=Fout+S; }
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		Tp inline void write(T x,const char& ch)
    		{
    			if (x<0) pc('-'),x=-x; RI ptop=0; while (pt[++ptop]=x%10,x/=10);
    			while (ptop) pc(pt[ptop--]+48); pc(ch);
    		}
    		inline void flush(void)
    		{
    			fwrite(Fout,1,Ftop-Fout,stdout);
    		}
    		#undef tc
    		#undef pc
    }F;
    int main(){
    //	freopen("data.in","r",stdin);
    	F.read(n);for(register int i=1;i<=n;i++) F.read(p[i]);for(register int i=n+1;i<=2*n;i++) p[i]=p[i-n];
    	for(register int i=1;i<=n;i++){int j=i,sum=0;memset(maxx,0,sizeof(maxx));while(j!=i+n){int x=ask(p[j])+1;add(p[j],x);j++;sum=max(sum,x);}ans=min(ans,n-sum);}
    	F.write(ans,'
    ');return F.flush(),0;
    }
    //给定一个排列,每次可以把一个数取出插入到另一个位置,最小操作次数 -> 最长上升子序列 
    
    
  • 相关阅读:
    删除顺序表L中下标为p(0<=p<=length-1)的元素,成功返回1,不成功返回0,并将删除元素的值赋给e
    设顺序表中的数据元素递增有序,试着写一算法,将x插入到顺序表上的适当位置上,以保持该表的有序性。
    数据结构-顺序表基本操作的实现(含全部代码)【转】
    【转】结构体指针
    结构体(第十四章 )
    线性表
    第二章 c语言概述
    时间复杂度
    软件质量与测试 黑盒测试
    软件质量保证与测试 基本内容
  • 原文地址:https://www.cnblogs.com/jiangxuancheng/p/14259511.html
Copyright © 2020-2023  润新知