参见校长的博客
1s,512mb
给国是个神奇的国家。由于给太祖的治理有方(且发现了给国定理),给国科技光速发展,发明出了时光鸡。给太祖有幸成为第一个食用时光鸡的人。
一开始时光鸡会跳到 0 0 0 时刻。然后往后正常走每段时间,当到达 2 n + 1 2n+1 2n+1 时被捉住。但令给太祖没有想到的是,它所经过的时间线因为虫洞的影响被打乱了。具体来说, i i i 时刻和 j j j 时刻通过一个虫洞连接。如果时光鸡从 i − 1 i-1 i−1 到了 i i i 时刻,它会被立即传送到 j j j 时刻。如果时光鸡从 j − 1 j-1 j−1 到了 j j j 时刻,它会被立即传送到 i i i 时刻。
总共有 n n n 对虫洞连接两个不同的时刻。每个 1 ∼ 2 n 1\sim 2n 1∼2n 的时刻恰好被一个虫洞连接。由于 0 0 0 时刻和 2 n + 1 2n+1 2n+1 时刻没有虫洞,容易证明时光鸡总是能到达 2 n + 1 2n+1 2n+1 时刻。由于时间久远,虫洞已经消失了,只能看到哪段时间上有鸡脚印。
你需要根据给太祖给出的记录还原出一种可行的虫洞匹配方案,或者告诉给太祖记录出错了。
输入格式
第一行两个整数 n , m n,m n,m,表示总时刻为 2 n + 1 2n+1 2n+1 以及存在脚印的时间总长。
接下来一行 m m m 个数,第 i i i 个数 a i a_i ai 表示 ( a i , a i + 1 ) (a_i,a_i+1) (ai,ai+1) 这段时间有鸡爪印。
输出格式
如果无解输出 No
,否则先输出一行 Yes
,然后输出 n n n 行,每行两个数 x , y x,y x,y ,表示 ( x , y ) (x,y) (x,y) 之间有一个虫洞相连。
如果有多种构造方案,输出任意一组即可。
样例输入
3 6
0 1 2 4 5 6
样例输出
Yes
1 5
2 6
3 4
数据范围与提示
m ≤ 2 n + 1 , a i − 1 < a i , a 1 = 0 , a m = 2 n m\leq2n+1,a_{i-1}
0 ≤ n ≤ 100000 , 0 ≤ m ≤ 200000 0\leq n\leq100000,0\leq m\leq 200000 0≤n≤100000,0≤m≤200000 。
我们令中间空出来的连续段个数为 A A A ,那么容易证明当 m − A − 1 m-A-1 m−A−1 为奇数的时候一定无解,因为你一定会将必走的区间匹配到不可走的区间上。
然后就有两种情况, ( m − A − 1 ) % 4 = 0 (m-A-1)\%4=0 (m−A−1)%4=0 和 ( m − A − 1 ) % 4 = 2 (m-A-1)\%4=2 (m−A−1)%4=2 。
第一种情况可以构造证明一定有解:
第二种情况我们发现也是可能有解的,当且仅当存在这么一种结构:
中间一段长度至少为 2 的极长可走区间,两边用不可走区间分隔,左右至少一边存在可匹配的可走区间。
以左边为例,如果左边存在一个可走区间了,就是上图中左边第一个红点,那么我们可以搭这样的结构:
该点与中间区间的左边第一个点匹配,两段不可走区间的两端连一个大拱桥,剩下的可匹配点就有 m − A − 3 m-A-3 m−A−3 个了,可以当作 % 4 = 0 \%4=0 %4=0 的情况构造。将经过该结构的过程删去,剩下的部分的行走刚好是连续的,容易证明正确性。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// #pragma GCC optimize(2)
using namespace std;
#define MAXN 200005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
// #define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
int a[MAXN],ct;
PR b[MAXN];
bool f[MAXN],aa[MAXN];
deque<int> q;
int main() {
freopen("shuttle.in","r",stdin);
freopen("shuttle.out","w",stdout);
n = read(); m = read();
int cn = 0,flg = 0,l = 0,r = 0;
for(int i = 1;i <= m;i ++) {
a[i] = read();
if(i > 1 && a[i] > a[i-1]+1) {
cn ++; aa[a[i]] = 1;
if(cn > 1 && a[i-1] == a[i-2]+1) flg = 1,r = i-1;
}
}
if((m - cn) % 4 == 1) {
for(int i = 2;i <= m;i ++) {
if(a[i] > a[i-1]+1) {
b[++ ct] = {a[i-1]+1,a[i]};
f[a[i-1]+1] = f[a[i]] = 1;
}
else q.push_back(a[i]);
}
while(!q.empty()) {
int A,B,C,D;
A = q.front(); q.pop_front();
B = q.front(); q.pop_front();
D = q.back(); q.pop_back();
C = q.back(); q.pop_back();
b[++ ct] = {A,C}; b[++ ct] = {B,D};
f[A] = f[B] = f[C] = f[D] = 1;
}
int p = 0;
for(int i = 1;i <= (n<<1);i ++) {
if(!f[i]) {
if(p) b[++ ct] = {p,i},p = 0;
else p = i;
}
}
sort(b + 1,b + 1 + ct);
printf("Yes\n");
for(int i = 1;i <= n;i ++) {
AIput(b[i].FI,' ');
AIput(b[i].SE,'\n');
}
return 0;
}
if((m - cn) % 4 == 3 && flg) {
l = r-1;
while(!aa[a[l]]) l --;
int p1,p2;
p1 = a[l-1]+1; p2 = a[r+1];
b[++ ct] = {p1,p2}; f[p1] = f[p2] = 1;
p1 = a[l]; p2 = a[r]+1;
b[++ ct] = {p1,p2}; f[p1] = f[p2] = 1;
int ll = l-1,rr = r+2;
while(aa[a[ll]]) ll --;
while(aa[a[rr]] && rr <= m) rr ++;
if(ll > 1) {
p1 = a[ll]; p2 = a[l+1];
b[++ ct] = {p1,p2}; f[p1] = f[p2] = 1;
}
else if(rr <= m) {
p1 = a[r]; p2 = a[rr];
b[++ ct] = {p1,p2}; f[p1] = f[p2] = 1;
}
else return printf("No\n"),0;
for(int i = 2;i <= m;i ++) {
if(a[i] > a[i-1]+1) {
if(i != l && i != r+1) {
b[++ ct] = {a[i-1]+1,a[i]};
f[a[i-1]+1] = f[a[i]] = 1;
}
}
else if(!f[a[i]]) {
q.push_back(a[i]);
}
}
while(!q.empty()) {
int A,B,C,D;
A = q.front(); q.pop_front();
B = q.front(); q.pop_front();
D = q.back(); q.pop_back();
C = q.back(); q.pop_back();
b[++ ct] = {A,C}; b[++ ct] = {B,D};
f[A] = f[B] = f[C] = f[D] = 1;
}
int p = 0;
for(int i = 1;i <= (n<<1);i ++) {
if(!f[i]) {
if(p) b[++ ct] = {p,i},p = 0;
else p = i;
}
}
sort(b + 1,b + 1 + ct);
printf("Yes\n");
for(int i = 1;i <= n;i ++) {
AIput(b[i].FI,' ');
AIput(b[i].SE,'\n');
}
return 0;
}
printf("No\n");
return 0;
}