入门OJ 1531【士兵训练】
描述
N个士兵排成一队进行军事训练,每个士兵的等级用1...K范围内的数来表示,
长官每隔1小时就随便说出M个等级a1,a2…am(1≤ai≤K,M个等级中允许有重复),
如果这M个等级组成的序列是排成一队的N个士兵等级序列的子序列,
那么训练继续;否则训练结束。长官想知道,M至少为多少时,训练才有可能结束。
例:士兵等级序列为1 5 3 2 5 1 3 4 4 2 5 1 2 3,
长官说出的等级序列为5 4,那么训练继续,
如果长官说出的等级序列为4 4 4,那么训练结束。
长官每隔1小时就随便说出M个等级a1,a2…am(1≤ai≤K,M个等级中允许有重复),
如果这M个等级组成的序列是排成一队的N个士兵等级序列的子序列,
那么训练继续;否则训练结束。长官想知道,M至少为多少时,训练才有可能结束。
例:士兵等级序列为1 5 3 2 5 1 3 4 4 2 5 1 2 3,
长官说出的等级序列为5 4,那么训练继续,
如果长官说出的等级序列为4 4 4,那么训练结束。
输入输出格式
输入
第一行为两个整数N和K(1≤N≤100000,1≤K≤10000),下面N行,每行一个数,按队伍顺序表示每个士兵的等级。
输出
包括一行,只包含一个数M,表示当长官至少说出M个等级的时候,训练才有可能结束。
输入输出样例
输入样例
14 5 1 5 3 2 5 1 3 4 4 2 5 1 2 3
输出样例
3
解题思路
首先,我以为这是一道水题,找等级数量最少的就行,然后WA。原来,他要求是子序列(度娘会告诉你的)。然后我就改了改代码。我们把这一列士兵分成几部分,使得每一部分都有所有的等级并且最短,然后只需要把分成的部分的数量加1就可以结束训练了
可能还是有点蒙,我们是取极端情况,取每一部分最后一个数,这个数在这一部分只出现了一次,就不会担心子序列连到前面,一直这么连,就求到了最长中最短的情况,再加一就找不到了。
题解
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,k,ans; 4 int a[100001],c[100001]; 5 int read()//好用的快读 6 { 7 int x=0,f=1; 8 char ch=getchar(); 9 while(ch<'0'||ch>'9'){ 10 if(ch=='-') 11 f=-1; 12 ch=getchar(); 13 } 14 while(ch>='0'&&ch<='9'){ 15 x=(x<<1)+(x<<3)+(ch^48); 16 ch=getchar(); 17 } 18 return x*f; 19 } 20 int main() 21 { 22 cin>>n>>m; 23 for(int i=1;i<=n;i++) 24 a[i]=read();//输入士兵 25 for(int i=1;i<=n;i++) 26 { 27 if(c[a[i]]==ans) 28 { 29 c[a[i]]++; 30 k++;//等级数 31 } 32 if(k==m) 33 { 34 ans++;//部分的数量 35 k=0; 36 } 37 } 38 cout<<ans+1;//加一输出 39 return 0; 40 }