Description
题目链接:AT1984[AGC001F]
给出一个元素集合为 {1,2,dots,N}( 1leq Nleq 500,000)的排列 P,当有 i,j (1leq i<jleq N)j-igeq K (1leq Kleq N-1) 且 P_{i}-P_{j}==1∣ 时,可以交换 P_{i} 和 P_{j}。
求:可能排列中字典序最小的排列
Solution
令 P_{a_i}=i,那么题中的限制条件就改为 P_i-P_{i-1}ge k,而要使原排列字典序最小也就相当于 a_i 的字典序最小。
然后如果 P_i-P_{i-1}<ki,j 之间的相对位置无法改变,此时只需要连一条反边,最后跑一边拓扑就好了。
但是如果这样的话建图会达到 mathcal O(N^2),但不难发现很多边都是重复的,所以可以用线段树优化建图。直接从 1 到 n 扫一遍,对于左边的只需要向其离 i 最近的连边即可,右边同理。
Code
代码语言:javascript复制#include<bits/stdc .h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define CI Cn int&
#define gc getchar
#define D isdigit(c=gc())
#define pc(c) putchar((c))
using namespace std;
namespace Debug{
Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f ;cerr<<'='<<x<<",";_debug(f 1,y...);}
Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
#define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
Tp I void read(Ty& x){char c;int f=1;x=0;W(!D) f=c^'-'?1:-1;W(x=(x<<3) (x<<1) (c&15),D);x*=f;}
Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x '0'),0):(write(x/10),pc(x '0'),0);}
Tp I void writeln(Cn Ty& x){write(x),pc('n');}
}using namespace FastIO;
Cn int N=5e5 10;
int n,k,a[N],b[N],fir[N],nxt[N<<1],son[N<<1],tot,in[N],Ans[N];
vector<int> p;
I void Add(CI x,CI y){in[y] ,nxt[ tot]=fir[x],fir[x]=tot,son[tot]=y;}
#define to son[i]
class SegmentTree{
private:
int T[N<<2];
#define mid (l r>>1)
#define PT CI x=1,CI l=1,CI r=n
#define LT x<<1,l,mid
#define RT x<<11,mid 1,r
#define PU(x) (T[x]=max(T[x<<1],T[x<<11]))
public:
I void U(CI p,CI v,PT){
if(l==r) return void(T[x]=v);
p<=mid?U(p,v,LT):U(p,v,RT),PU(x);
}
I int Q(CI L,CI R,PT){
if(L<=l&&r<=R) return T[x];
RI S=0;return L<=mid&&(S=max(S,Q(L,R,LT))),R>mid&&(S=max(S,Q(L,R,RT))),S;
}
}T;
priority_queue<int> q;
I void Topo(){
RI u,i;W(!q.empty()) q.pop();for(i=1;i<=n;i ) if(!in[i]) q.push(i);W(!q.empty()){
for(p.push_back(u=q.top()),q.pop(),i=fir[u];i;i=nxt[i]) if(!--in[to]) q.push(to);
}for(i=0;i<n;i ) Ans[p[i]]=n-i;return ;
}
int main(){
RI i,t;for(read(n,k),i=1;i<=n;i ) read(a[i]),b[a[i]]=i;
for(i=1;i<=n;i ) t=T.Q(b[i],min(b[i] k-1,n)),t&&(Add(b[i],b[t]),0),t=T.Q(max(1,b[i]-k 1),b[i]),t&&(Add(b[i],b[t]),0),T.U(b[i],i);
for(Topo(),i=1;i<=n;i ) writeln(Ans[i]);return 0;
}