Description
有n個數編號從0→n-1,兩種操作:
Q L R:詢問編號爲L→R-1的數中共有多少種不同的數
M X Y:將編號爲X的數改爲Y
共有m個操作
Input
第一行兩個數n,m
接下來m行,每行有兩種形式,如題目描述
Output
對於每一個Q操作,輸出相應的答案
Sample Input
7 4
1 2 1 3 2 1 4
Q 1 6
M 3 2
Q 1 6
Q 3 5
Sample Output
3
2
1
Data Constraint
30% n,m<=10000
100% n,m<=50000
數的範圍<=1000000
Solution
首先,你得會莫隊算法。
對於一個[l,r]如果能夠修改到[l+1,r][l-1,r][l,r+1][l,r-1]
那麼就可以使用莫隊算法。
莫隊算法的基本做法就是離線輸入所有的詢問,以l所在的塊爲第一關鍵字,**r(不同於後面的r所在的塊)**爲第二關鍵字進行排序,然後依次做下去,一個區間到下一個區間的修改直接暴力即可。
時間複雜度爲
爲什麼呢?
暴力是分別暴力l和r的,對於l,同一個塊內不超過,不超過個塊。對於r,每次逐漸增大,等到l跨過一個塊後又會變小,對於每個塊只會有一次變小所以每個塊O(n),不超過個塊,總不超過,
可以看看模板題,
這是不帶修改的,那帶修改的呢?
把[l,r]改爲[l,r,x],區間[l,r],第x次修改後的。同樣排序
所有的詢問,以l所在的塊爲第一關鍵字,r所在的塊爲第二關鍵字進行排序,x爲第三關鍵字排序,然後依次做下去,一個區間到下一個區間的修改直接暴力即可。
(當時寫錯了,感謝某大佬提醒,已修改)
複雜度自己證明。是根號級別的
另外,這裏的暴力是真正的暴力,從l到l’就是for i=l~l’,徹底的暴力。
對於這題,記錄一下每種有多少個,如果從0加到1則ans++,從1減到0則ans–,注意在修改時如果修改的不在l~r內,不需要修改ans
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define sz 1500
using namespace std;
int n,m,a[50100],bz[1000100],c[50100][3],tot,cot,ans[50100],d[50100],an;
struct note{
int l,r,x,s;
};
note b[50100];
bool cnt(note x,note y)
{
return (x.l/sz<y.l/sz)||((x.l/sz==y.l/sz)&&(x.r/sz<y.r/sz))||((x.l/sz==y.l/sz)&&(x.r/sz==y.r/sz)&&(x.x<y.x));
}
int main()
{
freopen("len.in","r",stdin);
freopen("len.out","w",stdout);
scanf("%d%d\n",&n,&m);
fo(i,1,n) scanf("%d",&a[i]);
scanf("\n");
int jy=0;
fo(i,1,m)
{
int x,y;char ch;scanf("%c%d%d\n",&ch,&x,&y);x++;
if (ch=='Q') b[++tot].l=x,b[tot].r=y,b[tot].x=jy,b[tot].s=tot;
else jy++,c[++cot][0]=x,c[cot][1]=y;
}
sort(b+1,b+tot+1,cnt);
int l=b[1].l,r=b[1].r,x=b[1].x;an=0;
fo(j,1,b[1].x)
{
c[j][2]=a[c[j][0]];a[c[j][0]]=c[j][1];
}
fo(i,l,r){
if (bz[a[i]]==0) an++;
bz[a[i]]++;
}
ans[b[1].s]=an;
fo(i,2,m)
{
if(b[i].x>x)
fo(j,x+1,b[i].x)
{
if (c[j][0]>=l&&c[j][0]<=r){
bz[a[c[j][0]]]--;
if (bz[a[c[j][0]]]==0) an--;
if (bz[c[j][1]]==0) an++;
bz[c[j][1]]++;
}
c[j][2]=a[c[j][0]];a[c[j][0]]=c[j][1];
}
else
fd(j,x,b[i].x+1)
{
if (c[j][0]>=l&&c[j][0]<=r){
bz[a[c[j][0]]]--;
if (bz[a[c[j][0]]]==0) an--;
if (bz[c[j][2]]==0) an++;
bz[c[j][2]]++;
}
a[c[j][0]]=c[j][2];
}
if (b[i].l>l)
{
fo(j,l,b[i].l-1){
bz[a[j]]--;
if (bz[a[j]]==0) an--;
}
}
else
{
fd(j,l-1,b[i].l){
if (bz[a[j]]==0) an++;
bz[a[j]]++;
}
}
if (b[i].r>r)
{
fo(j,r+1,b[i].r){
if (bz[a[j]]==0) an++;
bz[a[j]]++;
}
}
else
{
fd(j,r,b[i].r+1){
bz[a[j]]--;
if (bz[a[j]]==0) an--;
}
}
ans[b[i].s]=an;
l=b[i].l;r=b[i].r;x=b[i].x;
}
fo(i,1,tot) printf("%d\n",ans[i]);
}