传送门
解题思路
平衡树板子题。
每次所有的数加或减可以O(1)加或减限制,然后删除掉小于当前限制的点,统计答案。
加点时把原权值减去sum然后扔到Splay中,询问第k大时也要把查询的答案加上一个sum。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
using namespace std;
template<class T>inline void read(T &x)
{
x=0;register char c=getchar();register bool f=0;
while(!isdigit(c))f^=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(f)x=-x;
}
template<class T>inline void print(T x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar('0'+x%10);
}
const int maxn=3e5+5;
int n,rt,cnt,ans;
long long sum,m;
struct node{
int siz,cnt,son[2],fa;
long long val;
}tr[maxn];
void init(){
tr[rt].son[0]=tr[rt].son[1]=tr[rt].fa=tr[rt].siz=tr[rt].cnt=0;
rt=0;
}
int New(long long val,int fa){
cnt++;
tr[cnt].val=val;
tr[cnt].fa=fa;
tr[cnt].son[1]=tr[cnt].son[0]=0;
tr[cnt].cnt=tr[cnt].siz=1;
return cnt;
}
void update(int x){
tr[x].siz=tr[x].cnt;
if(tr[x].son[0]) tr[x].siz+=tr[tr[x].son[0]].siz;
if(tr[x].son[1]) tr[x].siz+=tr[tr[x].son[1]].siz;
}
void rotate(int x){
int y=tr[x].fa,z=tr[y].fa;
int c=(tr[y].son[1]==x);
tr[tr[x].son[!c]].fa=y;
tr[x].fa=tr[y].fa;
tr[y].fa=x;
if(z) tr[z].son[tr[z].son[1]==y]=x;
tr[y].son[c]=tr[x].son[!c];
tr[x].son[!c]=y;
update(y);
update(x);
}
void Splay(int x,int goal){
if(x==goal) return;
while(tr[x].fa!=goal){
int y=tr[x].fa,z=tr[y].fa;
if(z!=goal) ((tr[y].son[0]==x)^(tr[z].son[0]==y))?rotate(x):rotate(y);
rotate(x);
}
if(!goal) rt=x;
}
void insert(long long val){
if(!rt){
rt=++cnt;
tr[rt].val=val;
tr[rt].cnt=tr[rt].siz=1;
return;
}
int x=rt;
while(1){
if(tr[x].val==val){
tr[x].cnt++;tr[x].siz++;
Splay(x,0);
return;
}
if(tr[x].son[tr[x].val<val]) x=tr[x].son[tr[x].val<val];
else{
tr[x].son[tr[x].val<val]=New(val,x);
Splay(cnt,0);
return;
}
}
}
long long get_val(int tot){
if(tot>tr[rt].siz) return -sum-1;
int x=rt;
while(1){
while((tr[x].son[1]?tr[tr[x].son[1]].siz:0)+tr[x].cnt<tot) tot-=(tr[x].son[1]?tr[tr[x].son[1]].siz:0)+tr[x].cnt,x=tr[x].son[0];
if(tr[x].son[1]==0||tot>tr[tr[x].son[1]].siz){
return tr[x].val;
}else{
x=tr[x].son[1];
}
}
}
void work(){
insert(m-sum);
if(tr[rt].son[0]) ans+=tr[tr[rt].son[0]].siz;
tr[rt].son[0]=0;
update(rt);
if(tr[rt].cnt>1) tr[rt].cnt--;
else{
if(tr[rt].son[1]) tr[tr[rt].son[1]].fa=0,rt=tr[rt].son[1];
else init();
}
}
int main(){
read(n);read(m);
for(int i=1;i<=n;i++){
char c=getchar();
while(c<'A'||c>'Z') c=getchar();
int x;read(x);
if(c=='I'){
if(x<m) continue;
insert(x-sum);
}else
if(c=='A'){
sum+=x;
work();
}else
if(c=='S'){
sum-=x;
work();
}else{
print(get_val(x)+sum);
puts("");
}
}
print(ans);
return 0;
}