题目大意
给定
t
个可重集
有
m,n,t≤300000 ,所有元素都为不大于 109 的正整数。
题目分析
显然我们可以使用数据结构维护
T
集合以及
添加操作时,我们在对应
Ti
集合中插入该数,查询排名
rank
。如果
rank<=i
,说明它挤掉了一个数,那么我们就将
Ti
集合的第
i+1
名从
S
中删除,最后在
删除操作类似。
这个数据结构可以选用平衡树,配对堆等。其实权值线段树就可以解决问题,具体过程需要动态开点。
代码实现
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cctype>
using namespace std;
typedef long long LL;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch))
{
if (ch=='-')
f=-1;
ch=getchar();
}
while (isdigit(ch))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int S=40000005;
const int N=300005;
const int M=300005;
const int T=300005;
const int P=1000000000;
int n,m;
struct tree
{
int son[S][2],size[S];
int root[T];
LL sum[S];
int tot;
int newnode()
{
size[++tot]=0;
son[tot][0]=son[tot][1]=sum[tot]=0;
return tot;
}
void init()
{
memset(size,0,sizeof size);
memset(sum,0,sizeof sum);
memset(son,0,sizeof son);
tot=0;
for (int i=0;i<=300000;i++)
root[i]=newnode();
}
int kth(int rt,int rk,int l,int r)
{
if (l==r)
return l;
int mid=l+r>>1;
if (size[son[rt][1]]>=rk)
return kth(son[rt][1],rk,mid+1,r);
rk-=size[son[rt][1]];
return kth(son[rt][0],rk,l,mid);
}
int rank(int rt,int x,int l,int r)
{
if (l==r)
return 1;
int mid=l+r>>1;
if (x>mid)
return rank(son[rt][1],x,mid+1,r);
else
return size[son[rt][1]]+rank(son[rt][0],x,l,mid);
}
int change(int rt,int x,int l,int r,int delta)
{
if (!rt)
rt=newnode();
if (l==r)
{
sum[rt]+=delta*1ll*x;
size[rt]+=delta;
return rt;
}
int mid=l+r>>1;
if (x<=mid)
son[rt][0]=change(son[rt][0],x,l,mid,delta);
else
son[rt][1]=change(son[rt][1],x,mid+1,r,delta);
int ls=son[rt][0],rs=son[rt][1];
sum[rt]=sum[ls]+sum[rs];
size[rt]=size[ls]+size[rs];
return rt;
}
LL query(int rt,int kth,int l,int r)
{
if (l==r)
return l*1ll*min(kth,size[rt]);
int mid=l+r>>1;
if (kth<=size[son[rt][1]])
return query(son[rt][1],kth,mid+1,r);
else
return sum[son[rt][1]]+query(son[rt][0],kth-size[son[rt][1]],l,mid);
}
}t;
int main()
{
freopen("grimoire.in","r",stdin);
freopen("grimoire.out","w",stdout);
n=read(),m=read();
t.init();
for (int i=1;i<=m;i++)
{
char cmd=getchar();
while (!isalpha(cmd))
cmd=getchar();
int ti=read(),pi=read();
if (cmd=='B')
{
t.change(t.root[ti],pi,1,P,1);
int rk=t.rank(t.root[ti],pi,1,P);
if (rk<=ti)
{
if (t.size[t.root[ti]]>ti)
{
int num=t.kth(t.root[ti],ti+1,1,P);
t.change(t.root[0],num,1,P,-1);
}
t.change(t.root[0],pi,1,P,1);
}
LL ans=t.query(t.root[0],n,1,P);
printf("%lld\n",ans);
}
else
{
int rk=t.rank(t.root[ti],pi,1,P);
t.change(t.root[ti],pi,1,P,-1);
if (rk<=ti)
{
if (t.size[t.root[ti]]>=ti)
{
int num=t.kth(t.root[ti],ti,1,P);
t.change(t.root[0],num,1,P,1);
}
t.change(t.root[0],pi,1,P,-1);
}
LL ans=t.query(t.root[0],n,1,P);
printf("%lld\n",ans);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}