• Early Orders 数据结构 + 思维


    Early Orders 数据结构 + 思维

    题目大意:

    给你一个序列,让你找一个字典序最小的子序列,要求这子序列是一个前k个数的全排列。

    题解:

    难度不太,冷静思考。

    • 先赋值 (l = 1)

    • 首先从后往前找,找到最大的 (r) ,使得 ([r,n]) 存在一个子序列是前 k 个数的全排列

    • 那么,接下来只要找 ([l,r]) 的最小值 (pos) 即可,然后将 (pos) 这个位置的值标记,表示已经用过,并赋值 (l = pos+1) ,更新 (r) ,从 (r) 往后找,一直找到一个点 (v) ,这个点的值没有被用过,而且是这个值的最后一个位置, (r = v)

    • 重复第二个步骤,知道找完位置。

    我用的优先队列写的,写起来还是有点恶心,码量不大,要注意很多细节。

    #include <bits/stdc++.h>
    #define lson (id<<1)
    #define rson (id<<1|1)
    using namespace std;
    const int maxn = 2e5+10;
    typedef long long ll;
    int a[maxn],vis[maxn];
    vector<int>ans;
    struct node{
        int id,d;
        bool operator<(const node&a) const{
            return a.d<d;
        }
    };
    priority_queue<node> que;
    int last[maxn];
    int main(){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            last[a[i]] = i;
        }
        int l = 1,r = n,cnt = 0;
        for(int i=n;i>=1;i--){
            if(vis[a[i]]) continue;
            cnt++,vis[a[i]] = true,r = i;
            if(cnt==k) break;
        }
        memset(vis,0,sizeof(vis));
        for(int i=l;i<=r;i++) que.push(node{i,a[i]});
        while(!que.empty()){
            while(!que.empty()&&(vis[que.top().d]||que.top().id<l)) que.pop();
            if(que.empty()) break;
            node x = que.top();que.pop();
            vis[x.d] = true,ans.push_back(x.d),l = x.id + 1;
            while(r+1<=n){
                if(vis[a[r]]||last[a[r]]!=r) {
                    r++;
                    if(!vis[a[r]]) que.push(node{r,a[r]});
                }
                else break;
            }
        }
        for(int i=0;i<ans.size();i++){
            printf("%d",ans[i]);
            if(i==ans.size()-1) printf("
    ");
            else printf(" ");
        }
        return 0;
    }
    
  • 相关阅读:
    断开/删除 SVN 链接(.svn)的几种方法
    Android 中 ListView 常用属性合集
    Android 中 GridView 常用属性合集
    LeetCode-387-字符串中的第一个唯一字符
    LeetCode-374-猜数字大小
    LeetCode-290-单词规律
    LeetCode-278-第一个错误的版本
    LeetCode-383-赎金信
    LeetCode-367-有效的完全平方数
    LeetCode-350-两个数组的交集 II
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/14505864.html
Copyright © 2020-2023  润新知