https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3767
动态查询区间内有多少不同颜色
用set维护每种颜色出现的位置 set每次插入或擦除后仍满足单调性
对于[l,r]区间内有多少不同颜色 就看有多少位置i 其上颜色clr[i]之前出现的位置小于l 这样就讲问题转换为区间加和问题了 主要是修改操作时要照顾前后造成的影响比较麻烦
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l;
int r;
int val;
};
set <int> st[1000010];
node tree[20000010];
int clr[50010],root[50010],groot[50010];
int n,q,num;
int lowbit(int x)
{
return x&(-x);
}
int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}
int updateII(int rot,int tar,int val,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val+=val;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=updateII(tree[rot].l,tar,val,l,m);
else tree[cur].r=updateII(tree[rot].r,tar,val,m+1,r);
return cur;
}
void updateI(int bg,int tar,int val)
{
int i;
for(i=bg;i<=n;i+=lowbit(i))
{
groot[i]=updateII(groot[i],tar,val,0,n);
}
}
int queryII(int rot,int pl,int pr,int l,int r)
{
int res,m;
if(pl<=l&&r<=pr)
{
return tree[rot].val;
}
res=0,m=(l+r)/2;
if(pl<=m) res+=queryII(tree[rot].l,pl,pr,l,m);
if(pr>m) res+=queryII(tree[rot].r,pl,pr,m+1,r);
return res;
}
int queryI(int bg,int ed,int pl,int pr)
{
int res,i;
res=queryII(root[ed],pl,pr,0,n)-queryII(root[bg],pl,pr,0,n);
for(i=bg;i>=1;i-=lowbit(i)) res-=queryII(groot[i],pl,pr,0,n);
for(i=ed;i>=1;i-=lowbit(i)) res+=queryII(groot[i],pl,pr,0,n);
return res;
}
int main()
{
set <int> ::iterator it;
int i,p1,p2,l,r,m;
char op[10];
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&clr[i]);
st[clr[i]].insert(i);
}
num=0;
root[0]=build(0,n);
for(i=1;i<=n;i++)
{
it=st[clr[i]].lower_bound(i);
if(it==st[clr[i]].begin()) p1=0;
else p1=*(--it);
root[i]=updateII(root[i-1],p1,1,0,n);
}
for(i=1;i<=n;i++) groot[i]=root[0];
while(q--)
{
scanf("%s%d%d",op,&l,&r);
l++;
if(op[0]=='M')
{
if(clr[l]==r) continue;
it=st[clr[l]].lower_bound(l);
if(it==st[clr[l]].begin()) p1=0;
else
{
it--;
p1=*it;
it++;
}
it++;
if(it==st[clr[l]].end()) p2=-1;
else p2=*it;
it--;
st[clr[l]].erase(l);
updateI(l,p1,-1);
if(p2!=-1)
{
updateI(p2,l,-1);
updateI(p2,p1,1);
}
it=st[r].upper_bound(l);
if(it==st[r].begin()) p1=0;
else
{
it--;
p1=*it;
it++;
}
if(it==st[r].end()) p2=-1;
else p2=*it;
st[r].insert(l);
updateI(l,p1,1);
if(p2!=-1)
{
updateI(p2,l,1);
updateI(p2,p1,-1);
}
clr[l]=r;
}
else
{
printf("%d\n",queryI(l-1,r,0,l-1));
}
}
return 0;
}