Problem :
N只襪子排成一排,每次詢問一個區間內的襪子種隨機拿兩隻襪子顏色相同的機率。
Solution :
莫隊算法真的是簡單易懂又暴力。
莫隊算法用來離線處理區間詢問,要求每次區間的端點左右移動1能夠直接求出,經過第一關鍵字分塊排序左端點,第二關鍵字排序右端點,來合理安排詢問的順序,使得總的時間複雜度降低。每次詢問直接暴力修改就行。
假設分爲k塊,每塊大小爲n/k。
那麼左端點移動總的時間複雜度爲 n * n / k
右端點移動總的時間複雜度爲 k * n + n * kphp
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <string> #include <map> #include <vector> #include <queue> #include <ctime> using namespace std; #define f(i, x, y) for (int i = x; i <= y; ++i) #define fd(i, x, y) for (int i = x; i >= y; --i) #define rep(i, x, y) for (int i = x; i <= y; ++i) #define repd(i, x, y) for (int i = x; i >= y; --i) queue <int> Q; const int INF = 1e9 + 7; const int N = 200008; int n, m, q; vector <int> vec[N]; int dp[N]; int cnt[N], vis[N]; void init() { srand(time(NULL)); cin >> n >> m; for (int i = 1; i <= n; ++i) vec[i].clear(); for (int i = 1; i <= m; ++i) { int u, v; cin >> u >> v; vec[u].push_back(v); vec[v].push_back(u); } } void solve() { for (int i = 1; i <= n; ++i) dp[i] = rand() % 4; for (int i = 1; i <= n; ++i) Q.push(i), vis[i] = 1; while (!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = 0; for (int i = 0; i < 4; ++i) cnt[i] = 0; for (auto v : vec[u]) cnt[dp[v]]++; if (cnt[dp[u]] <= 1) continue; int qmin = INF, cl = 0; for (int i = 0; i < 4; ++i) if (cnt[i] < qmin) { qmin = cnt[i]; cl = i; } dp[u] = cl; for (auto v : vec[u]) if (dp[v] == cl && !vis[v]) Q.push(v); } for (int i = 1; i <= n; ++i) printf("%c",'a' + dp[i]); printf("\n"); } int main() { cin.sync_with_stdio(0); int T; cin >> T; for (int cas = 1; cas <= T; ++cas) { init(); solve(); } }