日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AcWing4084 号码牌 (并查集 / bitset优化Floyd)

發布時間:2023/12/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AcWing4084 号码牌 (并查集 / bitset优化Floyd) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接: 號碼牌

大致題意

給定一個長度為nnn的序列, 第iii個位置的值為aia_iai?. (保證aaa111~nnn的一個排列)

每個位置還有一個值did_idi?, 若滿足∣i?j=di∣|i-j=d_i|i?j=di?, 表示位置iii和位置jjj可以進行任意次交換.

問: 能否使得最終的序列滿足ai=ia_i = iai?=i.

解題思路

并查集 (數據太小了, 比賽時寫了個Floyd)

由于兩個位置的交換次數是任意次. 因此, 如果xxxyyy可以交換, 且yyyzzz可以交換, 則x,y,zx, y, zx,y,z三個位置處的aaa值可以互換.

上述分析可以推廣到一個有限大小的連通集合中.

因此, 我們只需要判斷每個連通集合內部aia_iai?值是否和該集合下標iii相同即可.


Floyd

mp[]mp[]mp[], 其中mp[val]mp[val]mp[val]記錄valvalval元素所處原序列的位置.

我們考慮題目的本質: 如果有ai≠ia_i \ne iai??=i, 表明iii位置需要與mp[a[i]]mp[a[i]]mp[a[i]]位置進行交換. 即: 我們需要判斷i,ji, ji,j兩個位置是否可達. 我們比較容易想到通過多源最短路進行處理.

考慮到本題并不需要求出兩點的距離, 只需要判斷是否可達, 因此若采用FloydFloydFloyd算法, 第三層循環可以認為是在求并集, 我們可以通過bitsetbitsetbitset進行優化.

寫上這個做法, 主要感覺這個題作為bitsetbitsetbitset優化FloydFloydFloyd入門題很友好.

AC代碼

并查集DSU

#include <bits/stdc++.h> #define rep(i, n) for (int i = 1; i <= (n); ++i) using namespace std; typedef long long ll; const int N = 1E2 + 10; int a[N], d[N];/* 并查集模版 */ struct DSU {int p[N];int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); }void merge(int a, int b) {a = find(a), b = find(b);if (a == b) return;p[b] = a;}void init(int n) { rep(i, n) p[i] = i; } }dsu;vector<int> v1[N], v2[N]; int main() {int n; cin >> n;rep(i, n) scanf("%d", &a[i]);rep(i, n) scanf("%d", &d[i]);dsu.init(n);rep(i, n) {int x = i - d[i], y = i + d[i];if (x >= 1) dsu.merge(i, x);if (y <= n) dsu.merge(i, y);}rep(i, n) v1[dsu.find(i)].push_back(a[i]), v2[dsu.find(i)].push_back(i);bool flag = 1;rep(i, n) {if (i != dsu.find(i)) continue;sort(v1[i].begin(), v1[i].end());if (v1[i] != v2[i]) flag = 0;}puts(flag ? "YES" : "NO");return 0; }

Floyd + bitset

#include <bits/stdc++.h> #define rep(i, n) for (int i = 1; i <= (n); ++i) using namespace std; typedef long long ll; const int N = 1E2 + 10; int a[N], d[N], mp[N]; bitset<N> can[N];void fact(int a, int b) { can[a][b] = can[b][a] = 1; } int main() {int n; cin >> n;rep(i, n) scanf("%d", &a[i]), mp[a[i]] = i;rep(i, n) {scanf("%d", &d[i]);if (i - d[i] > 0) fact(i, i - d[i]);if (i + d[i] <= n) fact(i, i + d[i]);can[i][i] = 1;}rep(k, n) rep(i, n) {if (can[i][k]) can[i] |= can[k];}bool flag = 1;rep(i, n) flag &= can[i][mp[i]];puts(flag ? "YES" : "NO");return 0; }

END

總結

以上是生活随笔為你收集整理的AcWing4084 号码牌 (并查集 / bitset优化Floyd)的全部內容,希望文章能夠幫你解決所遇到的問題。

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