题目描述:
雾。
题目分析:
好像是平衡树啊qwq
~~我不管,平衡树辣么长,我才不写呢~~
我们直接对每个树都建一颗位置线段树就行啦,维护每个位置节点上是否有本书。
别忘了离散化~
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxm=400100;
namespace seg{
int rt[maxm],sz;
int ls[maxm*8],rs[maxm*8],sum[maxm*8];
void insert(int &now,int l,int r,int ind,int num)
{
if(!now) now=++sz;
if(l>=r)
{
sum[now]+=num;
return;
}
int mid=(l+r)>>1;
if(ind<=mid) insert(ls[now],l,mid,ind,num);
else insert(rs[now],mid+1,r,ind,num);
sum[now]=sum[ls[now]]+sum[rs[now]];
}
int ask(int now,int l,int r,int ql,int qr)
{
if(!now) return 0;
if(ql<=l&&r<=qr) return sum[now];
int mid=(l+r)>>1;
int res=0;
if(ql<=mid) res+=ask(ls[now],l,mid,ql,qr);
if(qr>mid) res+=ask(rs[now],mid+1,r,ql,qr);
return res;
}
}
using namespace seg;
struct node{
int opt,l,r,id;
}q[maxm*4];
int hash[maxm*10],a[maxm],n,m;
int main()
{
scanf("%d%d",&n,&m);
int tot=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
hash[++tot]=a[i];
}
char s[10];
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='C')
{
q[i].opt=0;
scanf("%d%d",&q[i].l,&q[i].id);
}
else
{
q[i].opt=1;
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].id);
}
hash[++tot]=q[i].id;
}
std::sort(hash+1,hash+tot+1);
int t=std::unique(hash+1,hash+tot+1)-hash-1;
for(int i=1;i<=n;i++)
{
a[i]=std::lower_bound(hash+1,hash+t+1,a[i])-hash;
insert(rt[a[i]],1,n,i,1);
}
for(int i=1;i<=m;i++)
{
if(!q[i].opt)
{
insert(rt[a[q[i].l]],1,n,q[i].l,-1);
a[q[i].l]=std::lower_bound(hash+1,hash+t+1,q[i].id)-hash;
insert(rt[a[q[i].l]],1,n,q[i].l,1);
}
else
{
int id=std::lower_bound(hash+1,hash+t+1,q[i].id)-hash;
printf("%d\n",ask(rt[id],1,n,q[i].l,q[i].r));
}
}
return 0;
}