CF B. Moamen and k-subarrays(思维)

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也是一个十分重要的,需要关注的属性
// 如果给的操作可逆,可以从结果和原始状态 两方面综合考虑 找特征
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值