CF 612 題解 (haven't finished -- F)
阿新 • • 發佈:2021-07-22
C
發現是個經典的括號匹配。
D
emm...
想到按左端點排序。一個很直接的想法,對於第 \(i\) 段區間,前 \(i-k+1\) 段區間右端點的最大值會與它的左端點構成一個小區間,最後將這些區間合併即可。值得一提的是,在這之前你要將被包含的區間刪掉,不然會出現錯誤,這顯然。(emm...考試時就是沒有想到這個,以為這個做法不行)
另一個做法,類似掃描線/差分,將每個區間的左端點和右端點剝離,一個貢獻為 \(1\),一個貢獻為 \(-1\),從左到右掃描,若當前貢獻 \(\geqslant k\),則當前合法,細節比較多。
Code (way 2)
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <set> #define LL long long using namespace std; const int MAXN = 1e6 + 5; struct Node { int X, Y; bool operator < (const Node P) const { return X != P.X ? X < P.X : Y < P.Y; } }arr[MAXN], a[MAXN], c[MAXN << 1], v; int n, k, tot, t, q, ans1[MAXN], ans2[MAXN], cnt, maxx[MAXN]; int Max(int x, int y) { return x > y ? x : y; } int main() { scanf("%d%d", &n, &k); maxx[0] = -0x3f3f3f3f; for(int i = 1; i <= n; i ++) scanf("%d%d", &arr[i].X, &arr[i].Y); for(int i = 1; i <= n; i ++) { v.X = arr[i].X; v.Y = 1; c[++ tot] = v; v.X = arr[i].Y; v.Y = -1; c[++ tot] = v; } sort(c + 1, c + 1 + tot); cnt = 1; c[tot + 1].X = c[0].X = ans1[cnt] = 0x3f3f3f3f; int las = -1; for(int i = 1; i <= tot; ) { t += (c[i].Y == 1); int f = 0; f += (c[i].Y == -1); while(c[i + 1].X == c[i].X) i ++, t += (c[i].Y == 1), f += (c[i].Y == -1); if(t >= k) { if(ans1[cnt] == 0x3f3f3f3f) ans1[cnt] = c[i].X; q = 1; } las = c[i].X; i ++; t -= f;// printf("|%d|", t); if(t < k && q) { ans2[cnt] = las; cnt ++; q = 0; ans1[cnt] = 0x3f3f3f3f; // printf("^%d^", cnt); } } if(!q) printf("%d\n", -- cnt); for(int i = 1; i <= cnt; i ++) printf("%d %d\n", ans1[i], ans2[i]); return 0; } /* 4 2 1 4 1 3 1 2 1 1 */
E
(trick:一般這種排列變換問題都要考慮環,有時還要考慮奇偶。)
不妨手玩樣例,我們會發現一個性質:若 \(q[i]\) 的指向為奇環,則 \(p[i]\) 的指向也為奇環,並且會轉兩個位置。若 \(q[i]\) 的指向為偶環,則 \(p[i]\) 的指向會形成兩個同等大小的偶環。
只要看出這一點,那答案就很顯然了,反著來,若最後只有一個單獨的偶環,輸出 \(-1\)。
對於兩個相同的偶環,將它們交叉統計答案,可以證明任意兩個偶環組合都可以。
對於奇環,將它們的結果連起來,發現一個點要經過一個點到達它指向的節點,又因為 \(n+1\) 為偶數,所以這個點指向 \(x+(n+1)/2\)。(\(x\)
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <set> #include <vector> #define LL long long using namespace std; const int MAXN = 1e6 + 5; int n, a[MAXN], c[MAXN], len, ans[MAXN], b[MAXN]; bool vis[MAXN]; vector <int> v[MAXN]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i ++) scanf("%d", &a[i]); for(int i = 1; i <= n; i ++) { if(vis[i]) continue; int t = i; vis[t] = 1; len = 1; while(!vis[a[t]]) t = a[t], vis[t] = 1, len ++; c[len] ++; v[len].push_back(i); } for(int i = 1; i <= n; i ++) if(i % 2 == 0 && (c[i] & 1)) { printf("-1"); return 0; } for(int i = 1; i <= n; i ++) { if(i & 1) { for(unsigned int j = 0; j < v[i].size(); j ++) { int t = v[i][j]; for(int k = 0; k < i; k ++) b[k] = t, t = a[t]; t = v[i][j]; for(int k = 0; k < i; k ++) ans[t] = b[(k + i / 2 + 1) % i], t = a[t]; } } else { for(unsigned int j = 0; j < v[i].size(); j += 2) { int t1 = v[i][j], t2 = v[i][j + 1]; for(int k = 1; k <= i; k ++) ans[t1] = t2, ans[t2] = a[t1], t1 = a[t1], t2 = a[t2]; } } } for(int i = 1; i <= n; i ++) printf("%d ", ans[i]); return 0; }