做法一:
带修改莫队模板
第一关键字:左端点的块
第二:右端点块
第三:前面的修改次数,这里称time
#include
#include
#include
#include
#include
using namespace std;
const int N=10005;
int n,m;
int block,pos[N],col[N];
int query_num;
struct aa
{
int l,r,time,id,ans;
bool operator <(const aa &b)const
{
if (pos[l]!=pos[b.l]) return pos[l]=l&&pos<=r) del(pos);
from=col[pos];
col[pos]=to;
if (pos>=l&&pos<=r) insert(pos);
}
void out_time(int i)
{
int pos=q[i].x,to=q[i].y,from=q[i].z;
if (pos>=l&&pos<=r) del(pos);
col[pos]=from;
if (pos>=l&&pos<=r) insert(pos);
}
void work()
{
l=1,r=0,now=0;
for (int i=1;i<=query_num;i++)
{
for (;ra[i].r;r--) del(r);
for (;la[i].l;l--) insert(l-1);
for (;nowa[i].time;now--) out_time(now);
a[i].ans=tmp;
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&col[i]);
block=sqrt(n);
for (int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
char ch[2];
int x,y;
for (int i=1;i<=m;i++)
{
scanf("%s",ch);
scanf("%d%d",&x,&y);
if (ch[0]=='Q') a[++query_num]=(aa){x,y,time,i};
else q[++time]=(bb){x,y,0};
}
sort(a+1,a+query_num+1);
work();
sort(a+1,a+query_num+1,cmp);
for (int i=1;i<=query_num;i++) printf("%d\n",a[i].ans);
return 0;
}
做法二:
如果没有修改就是,处理不重复的基本思路,这个颜色上一个出现位置在l之前。
对于询问l~r,就是询问l~r中多少pre在l之前的。
考虑差分,其实就是在1~r中多少数小于l,主席树模板。
但是更改一个颜色就会出现,pre的改变。pre改变用set来维护,有更改就再套上一个树状数组就好。
注意:主席树的更改是很暴力的,其实就是暴力增加log 个节点罢了。
当然基本思路还是求区间小于等于一个数的个数。
还有就是修改一个颜色,会影响当前点的值和他后继的值,那么就是取后继和前驱,删除插入一个数。这用set就可以解决,原先分块写这题,更改这个地方暴力做的,麻烦了
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=11005;
const int N2=1000005;
int n,m,c[N];
//////////////////
int b[N],nn;
set col[N];
set::iterator it,pre,next;
//////////////////
struct Query
{
char ch[2];
int x,y;
}Que[N];
/////////////////
int tot,rt[N];
struct aa
{
int lc,rc,l,r,sum;
}a[N*20*20];
void build(int &u,int l,int r)
{
u=++tot;
a[u].l=l,a[u].r=r;
if (l==r) return;
int mid=(l+r)>>1;
build(a[u].lc,l,mid);
build(a[u].rc,mid+1,r);
}
void updata(int old,int &now,int pos,int add)
{
now=++tot;
a[now]=a[old];
a[now].sum+=add;
if (a[old].l==a[old].r) return;
int mid=(a[old].l+a[old].r)>>1;
if (pos<=mid) updata(a[old].lc,a[now].lc,pos,add);
else updata(a[old].rc,a[now].rc,pos,add);
}
int sum(int u,int t)
{
if (t==a[u].r) return a[u].sum;
int mid=(a[u].l+a[u].r)>>1;
if (t<=mid) return sum(a[u].lc,t);
return a[a[u].lc].sum+sum(a[u].rc,t);
}
///////////////////
inline int lowbit(int x){return x&(-x);}
void updata(int i,int last,int add)
{
int v;
for (;i<=n;i+=lowbit(i))
{
updata(rt[i],v,last,add);
rt[i]=v;
}
}
int query(int i,int t)
{
int ans=0;
for (;i;i-=lowbit(i)) ans+=sum(rt[i],t);
return ans;
}
/////////////////
int head[N];
void work(int l,int r)
{
printf("%d\n",query(r,l-1)-query(l-1,l-1));
}
void change(int pos,int now)
{
now=lower_bound(b+1,b+nn+1,now)-b;
int old=c[pos];
pre=next=it=col[old].lower_bound(pos);
pre--;next++;
updata(pos,*pre,-1);
if (next!=col[old].end()) updata(*next,pos,-1),updata(*next,*pre,1);
col[old].erase(it);col[now].insert(pos);c[pos]=now;
pre=it=next=col[now].lower_bound(pos);
pre--;next++;
updata(pos,*pre,1);
if (next!=col[now].end()) updata(*next,*pre,-1),updata(*next,pos,1);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&c[i]),b[++nn]=c[i];
for (int i=1;i<=m;i++)
{
scanf("%s",Que[i].ch);
scanf("%d%d",&Que[i].x,&Que[i].y);
if (Que[i].ch[0]=='R') b[++nn]=Que[i].y;
}
////
sort(b+1,b+nn+1);
nn=unique(b+1,b+nn+1)-b-1;
for (int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+nn+1,c[i])-b;
for (int i=1;i<=nn;i++) col[i].insert(0);
////
build(rt[0],0,n);
for (int i=1;i<=n;i++) rt[i]=rt[0];
for (int i=1;i<=n;i++)
{
updata(i,head[c[i]],1);
head[c[i]]=i;
col[c[i]].insert(i);
}
for (int i=1;i<=m;i++)
{
Query t=Que[i];
if (t.ch[0]=='Q') work(t.x,t.y);
else change(t.x,t.y);
}
return 0;
}