【2022杭电多校】第六场 Loop 【使用数据结构模拟】

链接

https://acm.hdu.edu.cn/showproblem.php?pid=7208

题意是说给你一个序列,你需要做exactly k次操作,每次操作选择一个区间[l,r],你可以将l位置的数移动到r位置,同时区间内的其他所有数左移一位
问你经过k次操作后能得到的字典序最大的数列是什么

思路

贪心!

思路1
每次找出\(a_i>a_{i-1}\)\(a_{i-1}\),将它拿出序列,放进一个优先队列中,此为一次操作,重复k次

注意不要k次暴力for查找,会超时,此处应用栈这个数据结构 细节见代码

View Code
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 3e5+10;
int t,n,k;
int a[N];
int s[N];
int top;

int main(){
    int t; scanf("%d",&t);
    while(t--){
        top=0;

        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        priority_queue<int>q;
        for(int i=1;i<=n;i++){
            while(top && s[top]<a[i] && k){
                q.push(s[top]);
                top--;
                k--;
            }
            s[++top]=a[i];
        }
        
        vector<int>ans;
        for(int i=1;i<=top;i++){
            while(!q.empty() && q.top()>s[i]){
                ans.push_back(q.top());
                q.pop();
            }
            ans.push_back(s[i]);
        }
        while(!q.empty()){
            ans.push_back(q.top());
            q.pop();
        }
        
        for(int i=0;i<ans.size();i++){
            if(i==0) printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }puts("");
    }
    system("pause");
    return 0;
}

思路2
定义一个结构体<value,position>,按照升序顺序存进set,每次从set尾部拿出一个元素,如果它可以移动到最前面来,那就可以一位一位移;如果不能就继续在set里找可以移动的最大的元素。

View Code
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int N = 3e5+10;
int t,n,k;
int a[N];
bool valid[N];

set<pii>st,q;
vector<int>ans;

int main(){
    int t; scanf("%d",&t);
    while(t--){
        st.clear();
        q.clear();
        ans.clear();

        int mxid=0;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            st.insert({a[i],i});
            valid[i]=0;
            if(i<=k+1&&a[i]>a[mxid]) mxid=i;
        }
        
        int ind=mxid;
        k-=(ind-1);
        valid[mxid]=1;

        for(int i=1;i<mxid;i++) q.insert({a[i],i});
        while(!st.empty()){
            if(k==0) break;
            auto now=*--st.end();
            int dis=now.second-1-ind;
            if(dis>=0 && k>=dis){
                valid[now.second]=1;
                for(int i=ind+1;i<now.second;i++){
                    q.insert({a[i],i});
                }
                k-=dis;
                ind=now.second;
            }
            st.erase(now);
        }
        for(int i=ind+1;i<=n;i++) valid[i]=1;
        
        for(int i=1;i<=n;i++){
            if(valid[i]){
                while(!q.empty()&&(*--q.end()).first>a[i]){
                    ans.push_back((*--q.end()).first);
                    q.erase(*--q.end());
                }
                ans.push_back(a[i]);
            }
        }
        while(!q.empty()){
            ans.push_back((*--q.end()).first);
            q.erase(*--q.end());
        }
        
        for(int i=0;i<ans.size();i++){
            if(i==0) printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }puts("");
    }
    system("pause");
    return 0;
}

p.s.最近多校遇到了很多模拟题,有的写了wa或者要调很久才能ac...还要多加练习呀!加油!

posted @ 2022-08-05 14:00  starlightlmy  阅读(73)  评论(0)    收藏  举报