日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

codeforces 7.22 E Permutation Shift

發布時間:2025/3/12 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 codeforces 7.22 E Permutation Shift 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

codeforces 7.22 E Permutation Shift

給出一個1到n的排列,每次可以交換兩個數,問在交換最多m次(m <= n/3)之后能不能得到由1 2 3 … n循環右移所得到的的排列,輸出所有能得到的排列和循環右移的次數。
數據范圍:n <= 3e5

有點腦洞的一道題。

由于最多交換m次,那么最多會有2m個數交換位置,而剩下的n - 2m個數是在原位置不變的。也即是,在循環右移k位之后,有至少n - 2m個數是與給出的排列對應位置的數相同的。

而在循環右移的過程中,對于每一位的數,只存在一個k使得讓這一位的數與給出的排列在同一位置是一樣的。這就代表著,在循環右移n-1次之后,每一次兩個排列相同的位數之和加起來是n。而要滿足條件的話,在循環右移k次之后,至少有n - 2m個數是相同的,n - 2m >= n / 3。也就是說最多存在三個k滿足條件。所以我們計數統計k,最多三次O(n)O(n)O(n)計算最少交換次數。總復雜度為O(n)O(n)O(n).

const int N = 3e5 + 10; int a[N], cnt[N], pos[N], b[N]; bool vis[N];int main() {//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);int T = 1;T = read();while (T --){int n = read(), m = read();for (int i = 0; i < n; i ++)cnt[i] = 0;for (int i = 0; i < n; i ++){a[i] = read();-- a[i];pos[a[i]] = i;int k = (i - a[i] + n) % n;cnt[k] ++; }queue <int> q;for (int i = 0; i < n; i ++){if (cnt[i] < n - 2 * m) continue;for (int j = 0; j < n; j ++){vis[j] = 0;b[(j + i) % n] = j;}int tot = 0;for (int j = 0; j < n; j ++){if (!vis[j]){++ tot;vis[j] = 1;int p = j;while (!vis[pos[b[p]]]){vis[pos[b[p]]] = 1;p = pos[b[p]];}}}tot = n - tot;if (tot <= m)q.push(i);}cout << q.size();while (!q.empty()){int now = q.front(); q.pop();cout << " " << now;}cout << endl;}return 0; }

總結

以上是生活随笔為你收集整理的codeforces 7.22 E Permutation Shift的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。