AT1984 [AGC001F] Wide Swap

2022-09-19 08:27:26 浏览数 (1)

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),但不难发现很多边都是重复的,所以可以用线段树优化建图。直接从 1n 扫一遍,对于左边的只需要向其离 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;
}
ode

0 人点赞