CF844 C 置换 水
由于每个数字只出现一次,离散化一下,置换求个循环节就好了。
/** @Date : 2017-08-25 01:39:39 * @FileName: C.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 2e5+20; const double eps = 1e-8; int a[N]; int pos[N]; vector<int>q[N]; int vis[N]; int main() { int n; while(cin >> n) { MMF(vis); MMF(pos); map<int,int>s; for(int i = 1; i <= n; i++) scanf("%d", a + i), pos[i] = a[i]; sort(a + 1, a + n + 1); for(int i = 1; i <= n; i++) s[a[i]] = i; for(int i = 1; i <= n; i++) a[i] = s[pos[i]]; int c = 0; for(int i = 1; i <= n; i++) { if(!vis[a[i]] && a[i] != i) { int cnt = 2; int np = a[i]; vis[i] = 1; while(a[np] != i || !vis[i]) { cnt++; vis[np] = 1; q[c].PB(np); np = a[np]; } vis[np] = 1; q[c].PB(np); q[c].PB(i); c++; } else if(a[i] == i) { q[c++].PB(a[i]); vis[i] = 1; } } printf("%d\n", c); for(int i = 0; i < c; i++) { printf("%d", q[i].size()); while(!q[i].empty()) { printf(" %d", q[i].back()); q[i].pop_back(); } printf("\n"); } } return 0; }