1 条题解

  • 0
    @ 2026-4-28 17:50:32

    看到有大小关系限制,考虑拓扑排序,并在拓扑的同时从大到小进行填数。

    问题转换为,对于拓扑队列中的所有元素(即 BB' 的位置),应该把最大的数填在哪个位置上。

    然后快快乐乐分类讨论就行了。

    约定: 蓝色块为已填,灰色块为可填(在拓扑队列中),白色块为不能填(不在拓扑队列中),优先级越小越先填。

    • Ai1>Ai<Ai+1:A_{i-1}>A_i<A_{i+1}:

    此时 $B'_i$ 的值越小越好,并且 $B'_i$ 的值每减小 $1$,答案增加 $2$,优先级为 $4$。
    
    • Ai1>Ai>Ai+1:A_{i-1}>A_i>A_{i+1}:

    此时从 $B'_{i-1}$ 到 $B'_{i+1}$ 对答案的贡献为 $B'_{i-1}-B'_{i+1}$,与 $B'_{i}$ 无关,优先级为 $2$。
    
    • Ai1<Ai<Ai+1A_{i-1}<A_i<A_{i+1}Ai1>Ai>Ai+1A_{i-1}>A_i>A_{i+1} 同理。

    • Ai1<Ai>Ai+1:A_{i-1}<A_i>A_{i+1}:

    此时 $B'_i$ 的值越大越好,并且 $B'_i$ 的值每增加 $1$,答案增加 $2$,优先级为 $0$。
    
    • i=1,Ai>Ai+1:i=1,A_i>A_{i+1}:

    此时 BiB'_i 的值越大越好,并且 BiB'_i 的值每增加 11,答案增加 11,优先级为 11

    • i=1,Ai<Ai+1:i=1,A_i<A_{i+1}:

    此时 BiB'_i 的值越小越好,并且 BiB'_i 的值每减小 11,答案增加 11,优先级为 33

    • i=ni=ni=1i=1 同理。

    拓扑的时候用优先队列,按照优先级排序即可。

    (其实这玩意儿写出来更像 Dijstra\text{Dijstra} /qd)

    代码

    分类讨论很麻烦,但代码不复杂。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=300010;
    inline int read(){
    	int x=0;
    	char c=getchar();
    	for(;!(c>='0'&&c<='9');c=getchar());
    	for(;c>='0'&&c<='9';c=getchar())
    		x=(x<<1)+(x<<3)+c-'0';
    	return x;
    }
    struct edge{
    	int v,to;
    }e[maxn<<1];
    int head[maxn],ecnt;
    void addedge(int u,int v){
    	e[++ecnt].v=v,e[ecnt].to=head[u],head[u]=ecnt;
    }
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    bitset<maxn>vis;
    int ru[maxn],n;
    int a[maxn],b[maxn];
    int Ans[maxn];
    int Num(int i){
    //返回对应位置优先级
    	if(i-1&&i<n){
    		if(!Ans[i-1]&&!Ans[i+1]) return 0;
    		if(Ans[i-1]&&Ans[i+1]) return 4;
    		return 2; 
    	}
    	if(i-1){
    		if(Ans[i-1]) return 3;
    		return 1;
    	} 
    	if(Ans[i+1]) return 3;
    	return 1;
    }
    void Solve(){
    	for(int i=1;i<=n;i++)
    		if(!ru[i]) q.push(make_pair(Num(i),i));
    	pair<int,int>t;
    	int cnt=0;
       //拓扑排序写法参考Dijstra堆优化版本
    	while(!q.empty()){
    		t=q.top(),q.pop();
    		if(vis[t.second]) continue;
    		//填过,continue
    		if(Num(t.second)^t.first) continue;
    		//不是当前状态(不是最新版本),continue
    		Ans[t.second]=b[++cnt],vis[t.second]=1;
    		if(t.second-1&&!ru[t.second-1]) 
    			q.push(make_pair(Num(t.second-1),t.second-1));
    		if(t.second<n&&!ru[t.second+1])
    			q.push(make_pair(Num(t.second+1),t.second+1));
    		for(int i=head[t.second];i;i=e[i].to){
    			ru[e[i].v]--;
    			if(!ru[e[i].v]) 
    				q.push(make_pair(Num(e[i].v),e[i].v));
    		}
    	}
    	
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read();
    	for(int i=1;i<=n;i++)
    		b[i]=read();
    	sort(b+1,b+1+n,greater<int>());
    	for(int i=1;i<n;i++)//加边
    		if(a[i]>a[i+1]) 
    			addedge(i,i+1),ru[i+1]++;
    		else addedge(i+1,i),ru[i]++;
    	Solve();
    	ll ans=0;
    	for(int i=1;i<n;i++)
    		ans+=abs(Ans[i]-Ans[i+1]);
    	printf("%lld\n",ans);
    	for(int i=1;i<=n;i++)
    		printf("%d ",Ans[i]);
    	return 0;
    }
    
    • 1

    信息

    ID
    4845
    时间
    1000ms
    内存
    64MiB
    难度
    10
    标签
    递交数
    8
    已通过
    4
    上传者