题解:P15652 [省选联考 2026] 排列游戏 / perm
考虑从小到大确定。
手玩一下发现可以这么构造:假设当前数
现在有两个问题:找
对于
为了把查找
#include<iostream>
#include<vector>
#include<set>
#include<map>
#define PII pair<int,int>
#define mp make_pair
#include "perm.h"
using namespace std;
const int N=3e4+5;
void init(int c,int t){
return;
}
map<PII,int> Map;
set<int> emp;
int ask(int l,int r){
if(Map.count(mp(l,r))) return Map[mp(l,r)];
return Map[mp(l,r)]=query(l,r);
}
vector<int> perm(int n){
Map.clear(),emp.clear();
Map[mp(0,n-1)]=n;
for(int i=0;i<n;i++) emp.insert(i);
vector<int> ans;
ans.resize(n);
int nl,nr,p=-1;
for(int i=0;i<n;i++){
int res=ask(i,n-1);
if(!res){
p=i-1;
break;
}
}
if(p==-1) p=n-1;
nl=nr=p,ans[p]=0;
emp.erase(p);
Map[mp(p,p)]=1;
for(int i=1;i<n;i++){
if(ask(nl,n-1)>i&&ask(0,nr)>i){
auto it=emp.lower_bound(nl);
ans[*it]=i;
emp.erase(it);
}
else if(ask(nl,n-1)>i){
for(int j=nr+1;j<n;j++){
if(ask(0,j)>i){
ans[j]=i;
emp.erase(j);
nr=j;
break;
}
}
}
else if(ask(0,nr)>i){
for(int j=nl-1;j>=0;j--){
if(ask(j,n-1)>i){
ans[j]=i;
emp.erase(j);
nl=j;
break;
}
}
}
}
return ans;
}