arc111c

arc111c

大意

略。。

思路

乱搞竟然过了(

首先,可以确定不成立的情况,当且仅当存在 \(k\) ,使 \(a_k\leq b_{p_k}\)

我们按 \(a_i\) 从大到小考虑。

不妨设当前未匹配的位置 \(a_i\) 的最大值在第 \(r\) 位,那么,我们交换 \(p_r\)\(p_{p_r}\)

相当于让 \(p_r\) 回到第 \(p_r\) 位上。

如果某一次交换时 \(r == p_r\) ,那么我们找到当前还未归位的 \(a_i\) 最大的位置,重复上面的操作。

我按 \(a_i\) 排序后用链表维护当前还未归位的序列,每次从末尾向前跳一步就能找到当前还未归位的最大值。

当然,常数比较大...

代码

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)

const int mod = 1e9+7;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;

int n;
int a[200200], b[200200], p[200200];
struct node {
    int id, val;
    void init(cint x, cint y) {
        id = x; val = y;
    }
    bool operator < (const node&a) const {
        return val < a.val;
    }
} s[200200];

int idt[200200];
int ans[200200][2], cnt;
int nx[200200], la[200200];

void cut(cint loc) {
    la[nx[loc]] = la[loc];
    nx[la[loc]] = nx[loc];
}

void NO() {
    cout << -1 << endl;
    exit(0);
}

int main() {
    bool flag = 0;
    cin >> n;
    for(int i=1; i<=n; i++) {cin >> a[i];}
    for(int i=1; i<=n; i++) {cin >> b[i];}
    for(int i=1; i<=n; i++) {cin >> p[i];}
    for(int i=1; i<=n; i++) {if(a[i] <= b[p[i]] && i != p[i]) flag = 1;}
    if(flag) NO();
    for(int i=1; i<=n; i++) s[i].init(i, a[i]);
    sort(s+1, s+1+n);
    for(int i=1; i<=n; i++) idt[s[i].id] = i;
    nx[0] = 1; la[n+1] = n;
    for(int i=1; i<=n; i++) nx[i] = i+1, la[i] = i-1;
    while(la[n+1] != 0) {
        flag = 1;
        int r = la[n+1];
        if(p[s[r].id] == s[r].id) cut(r);
        else {
            // cout << "r : " << r << endl << s[r].id << ' ' << s[r].val << endl;
            int my = p[s[r].id];
            cut(idt[my]);
            ans[++cnt][0] = s[r].id;
            ans[cnt][1] = my;
            swap(p[s[r].id], p[my]);
            if(p[my] == s[r].id) cut(r);
        }
    }
    cout << cnt << endl;
    for(int i=1; i<=cnt; i++)
        cout << ans[i][0] << ' ' << ans[i][1] << endl;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值