[BZOJ 3585] mex 【莫隊+分塊】

來源:互聯網
上載者:User

標籤:

題目連結:BZOJ - 3585

 

題目分析

區間mex,即區間中沒有出現的最小自然數。

那麼我們使用一種莫隊+分塊的做法,使用莫隊維護當前區間的每個數位出現次數。

然後求mex用分塊,將權值分塊(顯然mex 一定小於等於 n ,大於 n 的權值沒有意義,可以直接忽略),每塊大小 sqrt(n) 。

然後區間中的某個數的數量被減到0的時候就將它所在的塊的種類計數減一,添加數的時候類似。

然後枚舉每個塊,找到最小的中間有數不存在的塊(即種類數小於塊中的數的種數),然後到這個快裡直接從小一個一個找到第一個不存在的數。

這樣莫隊的複雜度和分塊的複雜度是相加的, O(n^1.5) + O(n^1.5) = O(n^1.5) 。

 

代碼
#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int MaxN = 200000 + 5, MaxQ = 200000 + 5, MaxB = 500 + 5;int n, m, BlkSize, MaxBlk;int A[MaxN], Blk[MaxN], L[MaxB], R[MaxB], Ans[MaxQ], Cnt[MaxN], V[MaxB], Size[MaxB];struct Query{int Idx, l, r, v;} Q[MaxQ];inline bool Cmp(Query q1, Query q2){if (q1.v == q2.v) return q1.r < q2.r;return q1.v < q2.v;}inline void Del_Num(int x){--Cnt[x];if (Cnt[x] == 0) --V[Blk[x]];}inline void Add_Num(int x){if (Cnt[x] == 0) ++V[Blk[x]];++Cnt[x];}void Pull(int f, int x, int y){if (x == y) return;if (f == 0){if (x < y){for (int i = x; i < y; ++i)Del_Num(A[i]);}else{for (int i = x - 1; i >= y; --i)Add_Num(A[i]);}}else{if (x < y) {for (int i = x + 1; i <= y; ++i)Add_Num(A[i]);}else{for (int i = x; i > y; --i)Del_Num(A[i]);}}}int Get_Ans(){int ret = n;for (int i = 1; i <= MaxBlk; ++i)if (V[i] < Size[i]){for (int j = L[i]; j <= R[i]; ++j)if (Cnt[j] == 0){ret = j;break;}break;}return ret;}int main(){scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i){scanf("%d", &A[i]);if (A[i] > n) A[i] = n + 1;}BlkSize = (int)sqrt((double)n);for (int i = 0; i <= n; ++i) Blk[i] = i / BlkSize + 1;MaxBlk = Blk[n];for (int i = 1; i <= MaxBlk; ++i){L[i] = (i - 1) * BlkSize;R[i] = i * BlkSize - 1;Size[i] = R[i] - L[i] + 1;}R[MaxBlk] = n;Size[MaxBlk] = n - L[MaxBlk] + 1;for (int i = 1; i <= m; ++i){scanf("%d%d", &Q[i].l, &Q[i].r);Q[i].Idx = i;Q[i].v = Q[i].l / BlkSize;}sort(Q + 1, Q + m + 1, Cmp);for (int i = Q[1].l; i <= Q[1].r; ++i) Add_Num(A[i]);Ans[Q[1].Idx] = Get_Ans();for (int i = 2; i <= m; ++i){if (Q[i].r <= Q[i - 1].l) {Pull(0, Q[i - 1].l, Q[i].l);Pull(1, Q[i - 1].r, Q[i].r);}else{Pull(1, Q[i - 1].r, Q[i].r);Pull(0, Q[i - 1].l, Q[i].l);}Ans[Q[i].Idx] = Get_Ans();}for (int i = 1; i <= m; ++i) printf("%d\n", Ans[i]);return 0;}

  

[BZOJ 3585] mex 【莫隊+分塊】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.