【Codeforces】848C. Goodbye Souvenir
将头尾之差看成各位差。
设 p r e [ x ] pre[x] pre[x]为与 x x x同色的上一个位置。
那么答案就是 ∑ i = l r [ l ≤ p r e [ i ] ] ∗ ( i − p r e [ i ] ) \sum_{i=l}^{r} [l \le pre[i]]*(i-pre[i]) ∑i=lr[l≤pre[i]]∗(i−pre[i])
也就是 ∑ i = 1 r [ l ≤ p r e [ i ] ] ∗ ( i − p r e [ i ] ) \sum_{i=1}^{r} [l \le pre[i]]*(i-pre[i]) ∑i=1r[l≤pre[i]]∗(i−pre[i])
我们将每个位置看成 ( t , i , p r e [ i ] ) (t,i,pre[i]) (t,i,pre[i])
每个修改看成 ( t , r , l ) (t,r,l) (t,r,l)
那么就成了二维数点问题了。
直接上CDQ
#include<set>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;
set<int> co[MAXN];
int n,m,Top,a[MAXN],pre[MAXN];LL F[MAXN],Ans[MAXN];
struct xcw{int Type,x,y,f,id;}Q[7*MAXN];
#include<cctype>
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
return f?ret:-ret;
}
void Clear(int x){for(;x;x-=x&-x) F[x]=0;}
void Put(int x,int p){for(;x;x-=x&-x) F[x]+=p;}
LL Get(int x){LL Sum=0;for(;x<=n;x+=x&-x) Sum+=F[x];return Sum;}
bool cmpx(xcw x,xcw y){return x.x<y.x;}
bool cmpid(xcw x,xcw y){return x.id<y.id;}
void Solve(int L,int R){
if(L>=R) return;int mid=(R+L)>>1;
Solve(L,mid);Solve(mid+1,R);
for(int i=mid+1,j=L;i<=R;i++)
if(Q[i].Type==2){
for(;Q[j].x<=Q[i].x&&j<=mid;j++) if(Q[j].Type==1) Put(Q[j].y,Q[j].f);
Ans[Q[i].id]+=Get(Q[i].y);
}
for(int i=L;i<=mid;i++) Clear(Q[i].y);
sort(Q+L,Q+R+1,cmpx);
}
int main(){
// freopen("848C.in","r",stdin);
// freopen("848C.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
if(co[a[i]].empty()) pre[i]=0;else pre[i]=*--co[a[i]].end();
co[a[i]].insert(i);
Q[++Top]=(xcw){1,i,pre[i],i-pre[i],0};
}
for(int i=1;i<=n;i++) co[i].insert(0);
for(int i=1;i<=m;i++){
int Type=read();
if(Type==1){
int p=read(),x=read(),nxt;
Q[++Top]=(xcw){Type,p,pre[p],pre[p]-p,i};
if((++co[a[p]].lower_bound(p))!=co[a[p]].end()){
nxt=*++co[a[p]].lower_bound(p);
Q[++Top]=(xcw){Type,nxt,pre[nxt],pre[nxt]-nxt,i};
pre[nxt]=pre[p];
Q[++Top]=(xcw){Type,nxt,pre[nxt],nxt-pre[nxt],i};
}
co[a[p]].erase(p);a[p]=x;
co[a[p]].insert(p);pre[p]=*--co[a[p]].lower_bound(p);
Q[++Top]=(xcw){Type,p,pre[p],p-pre[p],i};
if((++co[a[p]].lower_bound(p))!=co[a[p]].end()){
nxt=*++co[a[p]].lower_bound(p);
Q[++Top]=(xcw){Type,nxt,pre[nxt],pre[nxt]-nxt,i};
pre[nxt]=p;
Q[++Top]=(xcw){Type,nxt,pre[nxt],nxt-pre[nxt],i};
}
}else{
int L=read(),R=read();
Q[++Top]=(xcw){Type,R,L,0,i};
}
}
Solve(1,Top);sort(Q+1,Q+Top+1,cmpid);
for(int i=1;i<=Top;i++) if(Q[i].Type==2) printf("%lld\n",Ans[Q[i].id]);
return 0;
}