CF270B Multithreading
题目
给定一个初始序列 { 1 , 2 , 3 , … , n } \{1 , 2 , 3 , \dots , n\} {1,2,3,…,n}。
每次指定一个数,让它到最前面。
求至少进行多少次操作,把这个序列变成 { a 1 , a 2 , a 3 , … , a n } \{a_1 , a_2 , a_3 , \dots , a_n\} {a1,a2,a3,…,an}( a i a_i ai 互不相同)。
思路
直接上结论:只需要找出最后一个不满足题意的数,那它之前所有的数都要操作。
证明:考虑反证法,题意变成:把 { 1 , 2 , 3 , … , n } \{1 , 2 , 3 , \dots , n\} {1,2,3,…,n} 变成 { a 1 , a 2 , a 3 , … , a n } \{a_1 , a_2 , a_3 , \dots , a_n\} {a1,a2,a3,…,an},这样操作,应该把当前序列的第一个元素插到序列的任意一个地方。
经过观察和思考,发现:
-
最终序列是单调递增的,但初始序列不一定。
-
根据贪心,对于每个第一个元素,如果它后面存在比它小的 a k a_k ak,那么当前序列就不是最终序列。
-
转化后的题意告诉我们,只能对第一个数进行操作,所以此时必须操作。
-
由于题目保证了 a i a_i ai 互不相同,所以我们总能找到这时第一个元素的最终位置,并且插入进去。
所以对于每个不符合要求的 a i a_i ai,最多一次操作就能令其符合要求。
因为反证的题意只允许我们操作第一个元素,所以即使当前这一位已经满足了,它后面还有没有满足的元素,那它也必须操作。
得证:只需要找出最后一个不满足题意的数,那它之前所有的数都要操作。
上代码(码风奇特,勿喷)
#include <bits/stdc++.h> //万能头
using namespace std; //命名空间
int a[100001]; //定义数组
int main() //主函数
{
int n , ans = 0; //变量不多解释
cin >> n; //输入n
for(int i = 1; i <= n; i++) //输入a数组
{
cin >> a[i];
}
for(int i = 2; i <= n; i++) //遍历一遍找答案,注意不要遍历a[1]
{
if(a[i - 1] > a[i]) //判断如果符合条件
{
ans = i - 1; //更新ans
}
}
cout << ans << endl; //输出答案
return 0; //完美结束
}
温馨提示:
题目千万条,诚信第一条,代码不规范,棕名两行泪。别抄了昂,就这题你也抄?看看思路行了昂