P6198, Can You Help ZSGW (Preliminary questions for Luogu Monthly Competition and Wuhan University Competition)

Niu Ke topic link
Luo Gu topic link

There are too few questions about the divide-and-conquer type, and I see a wonderful way of writing, so after studying, summarize and record this question yourself

Topic:

There is an arrangement. It is known that when we execute the monotonic stack algorithm for this arrangement, the size of the monotonic stack after traversing to each position. Some positions may be missing. The input is -1. Find an arrangement with the smallest lexicographic order that satisfies this situation.

Ideas:

The first thing we should do is to complete this monotonous stack array b. Due to the characteristics of the monotonic stack algorithm, the monotonic stack array must meet several characteristics:

  • b[1] = 1
  • 若 b[i] > b[i −1],则 b[i] = b[i −1] +1,且 a[i] > a[i −1]。
  • For b [i] <= b [i −1], there must be a [i] <a [i −1].

We fill in each grid of −1 from left to right, then the strategy should be:

  • Young i = 1, b [i] = 1.
  • Otherwise, if we fill in a number smaller than b [i −1], in the output answer, a [i −1]> a [i], it will not be a good idea in lexicographic order. So we should fill in b [i −1] +1.
    After completing the array, the rule is as follows: First of all, we can find that all the positions of 1 form a descending sequence with the last 1 cut off. Then for each sub-interval divided by 1, 2 will also meet a similar rule. The same is true for subinterval 3, which is further divided by 2.

Code:

In the divide and conquer function, start to find the positions of all 1, fill in the numbers in descending order, and then delete the positions where the vector is 1, and then use 2,3 ... for each divided interval.

#include <iostream>
#include<stdio.h>
#include<vector>
#include<string>
#include<stack>
#include<algorithm>
using namespace std;
#define auto vector<int>::reverse_iterator
const int N=1e5+10;
vector<int>v[N];
stack<int>s;
int n;
int cur=1;
int a[N];
int b[N];
//每次运行完,都能被保证v和s清空了

void fill_arr(){
    a[1]=1;
    for(int i=2;i<=n;i++){
        if(a[i]==-1)a[i]=a[i-1]+1;
    }
}
void dfs(int l,int r,int pos){
    if(l>r)return;
    auto ed =v[pos].rend();
    for(auto i=v[pos].rbegin();i!=ed;i++){
        if(*i<=r)s.push(*i);
        else break;
    }
    while(!s.empty()&&s.top()>=l)b[s.top()]=cur++,s.pop();
    int xx = v[pos].back();
    dfs(l,xx-1,pos+1);
    v[pos].pop_back();
    while(!v[pos].empty()&&v[pos].back()<=r){
        dfs(xx+1,v[pos].back()-1,pos+1);
        xx = v[pos].back();
        v[pos].pop_back();
    }
    dfs(xx+1,r,pos+1);
    
}
void gao(){
    cur=1;
    fill_arr();
    for(int i=n;i;i--){
        v[a[i]].push_back(i);
    }
    dfs(1,n,1);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        gao();
        for(int i=1;i<=n;i++)printf("%d ",b[i]);
        puts("");
    }
}

Guess you like

Origin www.cnblogs.com/gzr2018/p/12702999.html