题解 CF848C 【Goodbye Souvenir】
我这题共写了四种做法,其中两种可以通过。感兴趣的可以去博客里面看,这里仅给出正解。
思路
考虑最后的减去开始的等价于每一位减去前面的。
即位置
那么题目转化为二维数点:一维是位置
当
询问可以变为查询以
然而这个矩形不好看,似乎还要差分?
其实并不用。考虑
时间复杂度应该是
代码
#include<bits/stdc++.h>
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 101010
typedef long long ll;
template<typename T>
inline void read(T& t)
{
t=0;char f=0,ch=getchar();
double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.')
{
ch=getchar();
while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
}
t=(f?-t:t);
}
template<typename T,typename... Args>
inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m,Q;
int a[sz];
int pre[sz],nxt[sz];
set<int>s[sz];
int calcPre(int x,int col){set<int>::iterator it=s[col].lower_bound(x);--it;return *it;}
int calcNxt(int x,int col){return *(s[col].upper_bound(x));}
ll ans[sz];
struct hh
{
int type; // 0:modify 1:query
int x,y,val;
int id;
}q[sz*6];
inline bool cmp(const hh &x,const hh &y)
{
if (x.type!=y.type) return x.type<y.type;
if (x.type) return x.y<y.y;
return x.x<y.x;
}
inline void calc(int x,int v) // pre[x]->v
{
q[++m]=(hh){0,x,pre[x],pre[x]-x,0};
pre[x]=v;
q[++m]=(hh){0,x,v,x-v,0};
}
ll sum[sz];
void add(int x,ll v){ if (!x) return; while (x<=n) sum[x]+=v,x+=(x&(-x)); }
ll query(int x){ ll ret=0; while (x) ret+=sum[x],x-=(x&(-x)); return ret; }
void solve(int l,int r)
{
if (l==r) return;
int mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
int p=l-1;
rep(i,mid+1,r) if (q[i].type)
{
while (p<mid&&(q[p+1].type||q[p+1].x<=q[i].y))
{
++p;
if (!q[p].type) add(q[p].y,q[p].val);
}
ans[q[i].id]+=query(n)-query(q[i].x-1);
}
rep(i,l,p) if (!q[i].type) add(q[i].y,-q[i].val);
sort(q+l,q+r+1,cmp);
}
int main()
{
file();
int x,y,z;
read(n,Q);
rep(i,1,n) s[i].insert(0),s[i].insert(n+1);
rep(i,1,n) read(a[i]),s[a[i]].insert(i);
rep(i,1,n) pre[i]=calcPre(i,a[i]),nxt[i]=calcNxt(i,a[i]),q[++m]=(hh){0,i,pre[i],i-pre[i],0};
int c=0;
while (Q--)
{
read(z,x,y);
if (z==1)
{
if (y==a[x]) continue;
int Pre=calcPre(x,y),Nxt=calcNxt(x,y);
s[a[x]].erase(x);s[y].insert(x);
a[x]=y;
if (nxt[x]!=n+1) calc(nxt[x],pre[x]);
if (pre[x]!=0) nxt[pre[x]]=nxt[x];
if (Pre!=0) nxt[Pre]=x;
if (Nxt!=n+1) calc(Nxt,x);
calc(x,Pre);
nxt[x]=Nxt;
}
else ++c,q[++m]=(hh){1,x,y,0,c};
}
solve(1,m);
rep(i,1,c) printf("%lld\n",ans[i]);
return 0;
}