codeforces 7.22 E Permutation Shift
生活随笔
收集整理的這篇文章主要介紹了
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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vuex使用详解,附加项目遇到的问题(简
- 下一篇: codeforces 7.22 F Pa