bzoj3585 莫隊 分塊

2021-08-21 14:03:06 字數 1952 閱讀 2421

description

有乙個長度為n的陣列。m次詢問,每次詢問乙個區間內最小沒有出現過的自然數。

input

第一行n,m。

第二行為n個數。

從第三行開始,每行乙個詢問l,r。

output

一行乙個數,表示每個詢問的答案。

sample input

5 52 1 0 2 1

3 32 3

2 41 2

3 5sample output

1hint

資料規模和約定

對於100%的資料:

1<=n,m<=200000

0<=ai<=109

1<=l<=r<=n

對於30%的資料:

1<=n,m<=1000

source

by 佚名提供

顯而易見我們可以發現,大於

n n

的數是不會對答案產生貢獻的。

我們將大於

n' role="presentation" style="position: relative;">n

n的數變為

n n

統計答案。 將1

' role="presentation" style="position: relative;">11~

n n

的數分塊,每塊記錄乙個數字表示塊內出現過的自然數的個數。

然後上莫隊暴力維護即可。

#include

using namespace std;

int n , q , k;

int a[201000] , belong[201000];

int flag[201000];

int sum[500] , t;

struct dataq[201000];

intread()

while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();

if(flag) return sum;

else

return -sum;

} bool mycmp(data a,data b)

void init()

for(int i = 1;i <= q;++i)

q[i].l = read() , q[i].r = read() , q[i].id = i;

k = sqrt(n);

if(k * k < n) t = k + 1,sum[t] = k*k + k - n;

else t = k;

for(int i = 1,j = k,t = 1;i <= n;i += k,j += k,t++)

if(j <= n) for(int

x = i;x

<= j;++x) belong[x] = t;

else

for(int

x = i;x

<= n;++x) belong[x] = t;

sort(q + 1,q + q + 1,mycmp);

return;

}void add(int

x)void dele(int

x)int

print()

int out[201000];

void solve()

for(int i = 1;i <= q;++i)

printf("%d\n",out[i]);

return;

}int main()

bzoj3585 mex 莫隊 分塊

ac通道 題解 這題思維上有些難度,蒟蒻不得不 了popoqqq大爺題解。將1 n之間的自然數分成根號n塊,每個塊記錄當前塊中已經出現的不同的自然數的個數。那麼在查詢時只需要檢驗每個塊是否滿足r i l i 1 blo i 找到第乙個不滿足以上條件的,然後在該塊內暴力查詢即可。bzoj 3585 b...

BZOJ 3585 Mex 莫隊 分塊

description 有乙個長度為n的陣列。m次詢問,每次詢問乙個區間內最小沒有出現過的自然數。input 第一行n,m。第二行為n個數。從第三行開始,每行乙個詢問l,r。output 一行乙個數,表示每個詢問的答案。examples sample input 5 52 1 0 2 1 3 32 ...

BZOJ3585 mex 莫隊 分塊

顯然可以離線主席樹,這裡用莫隊 分塊做。分塊的乙個重要思想是實現修改與查詢時間複雜度的均衡,這裡莫隊和分塊互相彌補。考慮暴力的分塊做法,首先顯然大於n的數直接忽略,於是將值域分成sqrt n 份,每塊記錄塊內的所有值是否在此當前區間內都已存在。這樣每次暴力從l到r分別放入這個表,最後從小到大詢問每個...