AT1984 [AGC001F] Wide Swap

Description

题目链接:AT1984[AGC001F]

给出一个元素集合为 ${1,2,\dots,N}$( $1\leq N\leq 500,000$)的排列 $P$,当有 $i,j (1\leq i<j\leq N)$满足$j-i\geq K (1\leq K\leq 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}|<k$,则 $i,j$ 之间的相对位置无法改变,此时只需要连一条反边,最后跑一边拓扑就好了。

但是如果这样的话建图会达到 $\mathcal O(N^2)$,但不难发现很多边都是重复的,所以可以用线段树优化建图。直接从 $1$ 到 $n$ 扫一遍,对于左边的只需要向其离 $i$ 最近的连边即可,右边同理。

Code

#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%10+'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<<1|1,mid+1,r
        #define PU(x) (T[x]=max(T[x<<1],T[x<<1|1]))
    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;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇