傳送門
給乙個序列,每個位置對應乙個值,支援下面兩種操作:
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還沒有學過程式設計,且覺得頭腦風暴太浪費腦力了,所以向你來尋求幫助。輸入檔案第一...