cdq分治的題 不過要先推出維度的關係
顯然想要得出一種數的答案 我們需要知道這種數在區間裏面出現的位置 最後的位置減去最前面的位置即可
但是我們無法很便捷的找到最後和最前的位置 卻可以找出所有出現的位置
設 pre[i] 爲i位置的數上一次出現的位置 對於每一個這樣的對(i和pre[i]) 他們的貢獻是 i-pre[i]
那麼一種數對於整個區間的貢獻就是
i<=R pre[i]>=L 的所有貢獻和
三個維度分別是 時間,當前位置 i 和pre[i]
對於每一個詢問 它的三個維度我們稍微改一下 設置爲 時間 R和L
我們加入 i <= R 的所有修改 通過樹狀數組(下標爲pre[i])維護後綴和 詢問 >=L 的所有貢獻即可
另外我們要用set維護 pre[i]的變化 也就是當p位置修改以後 我們要把修改前的 i和pre[i]的關係進行修改 還要把 i的後繼和pre[i]的關係進行修改 修改完以後 也要加入一些關係 (手動模擬一下就懂了)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
typedef long long ll;
set<int>col[N];
int n,m,val[N],a[N];
struct cd{
int op,p,pr,val,id;
}q[N*10],p[N*10];
int pre[N],tot;
ll c[N],ans[N];
void add(int x,ll val){
while(x){
c[x]+=val;
x-=x&-x;
}
}
ll query(int x){
ll ret = 0;
while(x<=n){
ret+=c[x];
x+=x&-x;
}
return ret;
}
void clear(int x){
while(x){
c[x]=0;
x-=x&-x;
}
}
bool cmp(cd a,cd b){
return a.p<b.p;
}
void cdq(int L,int R){
if(L==R) return;
int M = L+R>>1;
cdq(L,M);cdq(M+1,R);
int j = L,c = L;
for(int i = M+1; i <= R; i++){
while(j<=M&&q[j].p<=q[i].p){
if(q[j].op==1) add(q[j].pr,q[j].val);
p[c++]=q[j++];
}
if(q[i].op==2) ans[q[i].id]+=query(q[i].pr);
p[c++]=q[i];
}
for(int i = L; i < j; i++) if(q[i].op==1) clear(q[i].pr);
for(int i = j; i <= M; i++) p[c++]=q[i];
for(int i = L; i < c; i++) q[i]=p[i];
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
if(col[a[i]].empty()) pre[i]=0; else pre[i]=*--col[a[i]].end();
col[a[i]].insert(i);
q[++tot]=(cd){1,i,pre[i],i-pre[i],0};
}
for(int i = 1; i <= n; i++) col[i].insert(0);
int qt = 0;
for(int i = 1; i <= m; i++){
int op,x,y,nex;
scanf("%d%d%d",&op,&x,&y);
if(op==1){
q[++tot]=(cd){op,x,pre[x],pre[x]-x,0};
if(++col[a[x]].lower_bound(x)!=col[a[x]].end()){
nex = *++col[a[x]].lower_bound(x);
q[++tot]=(cd){op,nex,pre[nex],pre[nex]-nex,0};
pre[nex]=pre[x];
q[++tot]=(cd){op,nex,pre[nex],nex-pre[nex],0};
}
col[a[x]].erase(x);a[x]=y;
col[a[x]].insert(x);pre[x]=*--col[a[x]].lower_bound(x);
q[++tot]=(cd){op,x,pre[x],x-pre[x],0};
if(++col[a[x]].lower_bound(x)!=col[a[x]].end()){
nex = *++col[a[x]].lower_bound(x);
q[++tot]=(cd){op,nex,pre[nex],pre[nex]-nex,0};
pre[nex]=x;
q[++tot]=(cd){op,nex,pre[nex],nex-pre[nex],0};
}
}else{
q[++tot]=(cd){op,y,x,0,++qt};
}
}
cdq(1,tot);
for(int i = 1; i <= qt; i++) printf("%lld\n",ans[i]);
return 0;
}