​http://codeforces.com/problemset/problem/849/E​

两种操作 一种是把p位置的颜色换为x 另一种是查询[l,r]内每种颜色出现位置的最大下标与最小下标之差的和

操作的先后次序作为第一维 每种颜色的当前位置作为第二维 上一次出现的位置作为第三维 前后位置之差作为加值 进行cdq分治 这样查询操作就转换为查询矩阵之和了

还有就是颜色的插入和删除比较麻烦 怎么苟怎么写就好

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct node1
{
int tp;
int x;
int y;
int val;
};

struct node2
{
int l;
int r;
ll val;
};

set <int> st[100010];
node1 order[1000010],tmp[1000010];
node2 tree[400010];
int ary[100010];
ll ans[100010];
int n,q,tot;

void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}

void update(int tar,int val,int cur)
{
tree[cur].val+=val;
if(tree[cur].l==tree[cur].r) return;
if(tar<=tree[2*cur].r) update(tar,val,2*cur);
else update(tar,val,2*cur+1);
}

ll query(int pl,int pr,int cur)
{
ll res;
if(pl<=tree[cur].l&&tree[cur].r<=pr) return tree[cur].val;
res=0;
if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}

void cdq(int l,int r)
{
int m,p,q,cnt,i;
if(l==r) return;
m=(l+r)/2;
cdq(l,m);
cdq(m+1,r);
p=l,q=m+1,cnt=l;
while(p<=m&&q<=r)
{
if(order[p].x<=order[q].x)
{
if(order[p].tp==1) update(order[p].y,order[p].val,1);
tmp[cnt++]=order[p++];
}
else
{
if(order[q].tp==2) ans[order[q].val]-=query(1,order[q].y,1);
else if(order[q].tp==3) ans[order[q].val]+=query(1,order[q].y,1);
tmp[cnt++]=order[q++];
}
}
while(q<=r)
{
if(order[q].tp==2) ans[order[q].val]-=query(1,order[q].y,1);
else if(order[q].tp==3) ans[order[q].val]+=query(1,order[q].y,1);
tmp[cnt++]=order[q++];
}
for(i=l;i<p;i++)
{
if(order[i].tp==1) update(order[i].y,-order[i].val,1);
}
while(p<=m) tmp[cnt++]=order[p++];
for(i=l;i<=r;i++) order[i]=tmp[i];
}

int main()
{
set <int> ::iterator it;
int i,op,p,x,l,r,p1,p2,cnt;
scanf("%d%d",&n,&q);
tot=0;
for(i=1;i<=n;i++)
{
scanf("%d",&ary[i]);
if(st[ary[i]].empty()) st[ary[i]].insert(i);
else
{
st[ary[i]].insert(i);
it=st[ary[i]].lower_bound(i);
it--;
tot++;
order[tot].tp=1,order[tot].x=i,order[tot].y=(*it),order[tot].val=i-(*it);
}
}
cnt=0;
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&p,&x);
it=st[ary[p]].lower_bound(p);
if(it!=st[ary[p]].begin())
{
it--;
p1=(*it);
it++;

tot++;
order[tot].tp=1,order[tot].x=p,order[tot].y=p1,order[tot].val=-(p-p1);

it++;
if(it!=st[ary[p]].end())
{
p2=(*it);
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p,order[tot].val=-(p2-p);
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p1,order[tot].val=p2-p1;
}
}
else
{
it++;
if(it!=st[ary[p]].end())
{
p2=(*it);
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p,order[tot].val=-(p2-p);
}
}

st[ary[p]].erase(p);
st[x].insert(p);
ary[p]=x;

it=st[x].lower_bound(p);
if(it!=st[x].begin())
{
it--;
p1=(*it);
it++;

tot++;
order[tot].tp=1,order[tot].x=p,order[tot].y=p1,order[tot].val=p-p1;

it++;
if(it!=st[x].end())
{
p2=(*it);
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p,order[tot].val=p2-p;
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p1,order[tot].val=-(p2-p1);
}
}
else
{
it++;
if(it!=st[x].end())
{
p2=(*it);
tot++;
order[tot].tp=1,order[tot].x=p2,order[tot].y=p,order[tot].val=p2-p;
}
}
}
else
{
scanf("%d%d",&l,&r);
cnt++;
if(l-1>=1)
{
tot++;
order[tot].tp=2,order[tot].x=l-1,order[tot].y=r,order[tot].val=cnt;
tot++;
order[tot].tp=2,order[tot].x=r,order[tot].y=l-1,order[tot].val=cnt;
tot++;
order[tot].tp=3,order[tot].x=l-1,order[tot].y=l-1,order[tot].val=cnt;
}
tot++;
order[tot].tp=3,order[tot].x=r,order[tot].y=r,order[tot].val=cnt;
}
}
build(1,n,1);
cdq(1,tot);
for(i=1;i<=cnt;i++) printf("%lld\n",ans[i]);
return 0;
}