B. Moamen and k-subarrays
题目
大意上,就是给一个长为n的数列,其中元素互不相同,给定k ,可将数列划分为k个子序列 把这些序列重排后,能否得到 一个升序数列。
扯淡
一开始看错题,直接毙掉
显然关键是看如何划分k个区间,每个区间必须升序才行,然后就开始搞模拟分割,交了,然后WA了,然后发现我模拟出来的东西,无法保证全局升序,就开始打各种标记瞎搞,成功把自己干掉。。。
思路
首先,可以将问题转化为求分割区间数量的最小值,只要这个k比最小值大或相等,一定可以达成目标。
然后,需要观察 ,分割区间的特征,因为这个操作是可逆的,分割后同样可以重排区间,得到原始序列。因此分割的子序列一定是排好的序列的一个子序列,也是原始序列的子序列。
所以,对原数列来说,子序列下标一定连续。对排好的序列来说,一定升序。
因此,我们只要对原序列排序后,尽可能的把下标仍连续的放一个区间即可。
AC代码
#include <bits/stdc++.h>
//#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 10;
void solve()
{
int n,k;
cin>>n>>k;
vector<PII> arr(n);
for(int i=0;i<n;i++)
{
cin>>arr[i].first;
arr[i].second=i;//记录原序列元素顺序
}
int cnt=1;//记录 两区间的间隔间接得到区间数量
sort(arr.begin(),arr.end());
for(int i=0;i<n-1;i++)
if(arr[i].second+1!=arr[i+1].second)
cnt++;
if(cnt<=k)puts("yes");
else puts("no");
}
signed main()
{
int T;
cin >> T;
while (T--)
solve();
return 0;
}
// 和排序有关的idx也是一个十分重要的,需要关注的属性
// 如果给的操作可逆,可以从结果和原始状态 两方面综合考虑 找特征