前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AT1984 [AGC001F] Wide Swap

AT1984 [AGC001F] Wide Swap

作者头像
yzxoi
发布2022-09-19 08:27:26
7510
发布2022-09-19 08:27:26
举报
文章被收录于专栏:OI

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}<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%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<<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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-05-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Description
  • Solution
  • Code
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档