BZOJ2453 維護佇列(分塊)

2021-09-30 16:21:46 字數 1628 閱讀 8663

傳送門

給乙個序列,每個位置對應乙個值,支援下面兩種操作:

1.修改某個位置的值。

2.詢問(l,r)區間內不同值的個數。

1.考慮分塊:統計ans[i][j]表示第i塊到第j塊的個數,容易發現對於每個詢問,只需檢視完整塊的個數和不完整塊的影響。時間複雜度o(

n⋅n√

) 。但修改會修改兩兩塊之間的ans[i][j],時間複雜度o(

n⋅m)

(這道題修改只有1000個,可以過去)。

2.莫隊演算法:如果沒有修改操作莫隊直接秒,有修改操作寫莫隊就有點麻煩,要加乙個時間的維度。具體不再贅述,可以嘗試一下,也可以過。

3.還是考慮分塊:對於每乙個位置記錄前面相同顏色最近出現的位置pre[i]。對於乙個查詢就是查詢塊中pre[i]小於l的個數。分塊並排序,塊內二分查詢。時間複雜度o(

n⋅n√

⋅log

n√) 。修改操作暴力修改,如果不同就重建。(反正只改乙個位置,最多也只重建前後影響的幾個塊)。時間複雜度m⋅

(n+n

√⋅lo

gn√)

。第一種和第三種本質上是差不多的,但第一種難寫一點,這裡給出第三種的**:

#include

using

namespace

std;

const

int maxn=3e4+50;

const

int maxm=3e4+50;

int s=140;

inline

int read()

while(isdigit(ch))

return i*f;

}int n,m,a[maxn],bg[maxn],ed[maxn],s1,pre[maxn],last[maxn],s,b[maxn];

char ch[2];

struct node

q[maxn];

inline

void l_b()

}inline

void pre()

for(int i=1;i*s<=n;i++)s=i,bg[i]=ed[i-1]+1,ed[i]=ed[i-1]+s;

if(ed[s]!=n)s++,bg[s]=ed[s-1]+1,ed[s]=n;

for(int i=1;i<=n;i++)b[i]=pre[i];

for(int i=1;i<=s;i++)sort(b+bg[i],b+ed[i]+1);

}int buf[50];

inline

void w(int x)

inline

int calc(int now,int val)

if(r==bg[now]-1)l=bg[now]-1;

return l-bg[now]+1;

}inline

void rebuild(int x)

int main()

}l_b();

pre();

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

a[q[i].pos]=q[i].val;

for(int j=1;j<=n;j++)

}else

else}}

}

bzoj 2453 維護佇列

你小時候玩過彈珠嗎?小朋友a有一些彈珠,a喜歡把它們排成佇列,從左到右編號為1到n。為了整個佇列鮮豔美觀,小朋友想知道某一段連續彈珠中,不同顏色的彈珠有多少。當然,a有時候會依據個人喜好,替換佇列中某個彈珠的顏色。但是a還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你來尋求幫助。輸入檔案第一...

BZOJ 2453 維護佇列

description 你小時候玩過彈珠嗎?小朋友a有一些彈珠,a喜歡把它們排成佇列,從左到右編號為1到n。為了整個佇列鮮豔美觀,小朋友想知道某一段連續彈珠中,不同顏色的彈珠有多少。當然,a有時候會依據個人喜好,替換佇列中某個彈珠的顏色。但是a還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你...

bzoj2453 維護佇列

你小時候玩過彈珠嗎?小朋友a有一些彈珠,a喜歡把它們排成佇列,從左到右編號為1到n。為了整個佇列鮮豔美觀,小朋友想知道某一段連續彈珠中,不同顏色的彈珠有多少。當然,a有時候會依據個人喜好,替換佇列中某個彈珠的顏色。但是a還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你來尋求幫助。輸入檔案第一...