题目链接:
题目链接
题意简述:
给定两个长度均为$n$的序列$A,B$
定义一次操作为:交换$A_i, A_j$,其中$i in [1, n], j in [1, n]$且$i neq j$
问是否能使用小于等于$n - 2$次操作,使得:$forall i in [1, n]$,总有$A_i leq B_i$?
其中$1 le n le 100, 000$
简要做法:
特别巧妙的一道题。
设排序后的数组分别为$A’$和$B’$,那么:
如果$exists i, j$满足$A’_i > B’_j$,那么一定是不可行的;
如果$exists i$满足$A’_i le B’_{i+1}$,那么一定是可行的。
排除了上述两种特殊情况后,考虑构建一个图:
对于$A$中的任意一个数$A_i$,设其在$A’$中的排名为$rank(A, i)$,
那么连一条$A_i to B_j$的边,其中$j$满足:$rank(B, j) = rank(A, i)$
显然这样会形成至少一个环,其中每条边$A_i to B_j$表示应该交换$A_i, A_j$
环的总长度就为交换次数,
那么如果只有一个环,就有$n - 1$条边,无法满足题意;
如果有多于一个的环,就有小于等于$n - 2$条边,满足题意。
参考代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
#define ll long long #define rgi register int #define rgl register long long #define il inline
const int N = 2e5 + 10;
int n, tot, cnt, num[N], nxt[N], vis[N]; int a[N], sortA[N], rankA[N]; int b[N], sortB[N], posB[N];
il int () { rgi x = 0, f = 0, ch; while(!isdigit(ch = getchar())) f |= ch ==
大专栏
[AtCoder]NIKKEI Programming Contest 2019-2 C - Swapsn class="string">'-'
; while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar(); return f ? -x : x; }
int main() { n = read(); for(rgi i = 1; i <= n; ++i) a[i] = num[++tot] = read(); for(rgi i = 1; i <= n; ++i) b[i] = num[++tot] = read(); std::sort(num + 1, num + tot + 1); tot = std::unique(num + 1, num + tot + 1) - (num + 1); for(rgi i = 1; i <= n; ++i) a[i] = std::lower_bound(num + 1, num + tot + 1, a[i]) - (num + 1) + 1; for(rgi i = 1; i <= n; ++i) b[i] = std::lower_bound(num + 1, num + tot + 1, b[i]) - (num + 1) + 1; for(rgi i = 1; i <= n; ++i) sortA[i] = a[i]; for(rgi i = 1; i <= n; ++i) sortB[i] = b[i]; std::sort(sortA + 1, sortA + n + 1); std::sort(sortB + 1, sortB + n + 1); for(rgi i = 1; i <= n; ++i) if(sortA[i] > sortB[i]) { puts("No"); return 0; } for(rgi i = 1; i <= n - 1; ++i) if(sortA[i + 1] <= sortB[i]) { puts("Yes"); return 0; } for(rgi i = 1; i <= n; ++i) posB[b[i]] = i; for(rgi i = 1; i <= n; ++i) rankA[sortA[i]] = i; for(rgi i = 1; i <= n; ++i) nxt[i] = posB[sortB[rankA[a[i]]]]; for(rgi i = 1; i <= n; ++i) if(!vis[i]) { int cur = i; do { vis[cur] = 1; cur = nxt[cur]; } while(!vis[cur]); cnt++; } puts(cnt == 1 ? "No" : "Yes"); return 0; }
|