题意:
给出n个操作和最低值min;
I:增加一个新的权值为k的节点;
A:将全部节点权值加k;
S:将全部节点权值减k;
F:查询当前第k大的权值;
无论何时若某权值小于min那么就要删除该点;
输出询问的结果以及总共删去的多少节点;
题解:
查询第k大值的问题,用平衡树来维护此题;
思路大概像线段树一样,用一个延迟标记来防止不需要的更新;
(以上思路纯属yy,时间复杂度O(nlogn)说出来我自己都不信)
插入查询不必细说,A操作不会涉及删除所以直接在根节点修改延迟标记就可以;
而S操作涉及删除权值小的点,那么就用记录当前子树的最小值;
当需要删除就下传延迟标记,再向左向右查找,然后特判中间;
旋转时当心标记的问题就好;
具体看代码吧。。。然而写的并不好;
HINT:
一开始权值就不够的不计入删去的之内;
Linux下随机值很大,所以treap写小根堆的小心。。。反正我被坑了;
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 111000
#define lson treap[treap[no].l]
#define rson treap[treap[no].r]
using namespace std;
struct node
{
int val,rnd,mi,cov,l,r,size;
}treap[N];
char str[100];
int low,cnt,tot;
void Pushup(int no)
{
treap[no].size=lson.size+rson.size+1;
treap[no].mi=min(treap[no].val,min(lson.mi,rson.mi));
}
void Pushdown(int no)
{
if(treap[no].cov)
lson.cov+=treap[no].cov,
rson.cov+=treap[no].cov,
lson.val+=treap[no].cov,
rson.val+=treap[no].cov,
lson.mi+=treap[no].cov,
rson.mi+=treap[no].cov,
treap[no].cov=0;
}
void lturn(int &no)
{
int p=treap[no].r;
treap[no].r=treap[p].l;
treap[p].l=no;
treap[p].size=treap[no].size;
Pushup(no);
no=p;
}
void rturn(int &no)
{
int p=treap[no].l;
treap[no].l=treap[p].r;
treap[p].r=no;
treap[p].size=treap[no].size;
Pushup(no);
no=p;
}
void insert(int &no,int val)
{
if(treap[no].size<=0)
{
treap[no].size=1;
treap[no].mi=treap[no].val=val;
treap[no].rnd=rand()%10000000;
return ;
}
if(treap[no].val<=val)
{
if(treap[no].l==0)
treap[no].l=++tot;
Pushdown(no);
insert(treap[no].l,val);
Pushup(no);
if(lson.rnd<treap[no].rnd)
Pushdown(treap[no].l),rturn(no),Pushup(no);;
}
else
{
if(treap[no].r==0)
treap[no].r=++tot;
Pushdown(no);
insert(treap[no].r,val);
Pushup(no);
if(rson.rnd<treap[no].rnd)
Pushdown(treap[no].r),lturn(no),Pushup(no);;
}
}
void del(int &no)
{
if(lson.size+rson.size==0)
{
treap[no].val=treap[no].mi=treap[no].rnd=~0u>>1;
treap[no].size=treap[no].l=treap[no].r=0;
cnt++,no=0;
return ;
}
if(lson.rnd>rson.rnd)
{
Pushdown(treap[no].r),lturn(no);
del(treap[no].l);
Pushup(no);
}
else
{
Pushdown(treap[no].l),rturn(no);
del(treap[no].r);
Pushup(no);
}
}
void update(int &no,int val)
{
if(treap[no].size<=0) return ;
if(treap[no].mi-val<low)
{
Pushdown(no);
update(treap[no].l,val);
update(treap[no].r,val);
if(treap[no].val-val<low)
del(no);
else
treap[no].val-=val,Pushup(no);
}
else
treap[no].val-=val,treap[no].mi-=val,treap[no].cov-=val;
}
int query(int &no,int k)
{
if(treap[no].size<=0) return -1;
Pushdown(no);
if(lson.size>=k)
return query(treap[no].l,k);
else if(lson.size+1<k)
return query(treap[no].r,k-1-lson.size);
else
return treap[no].val;
}
int main()
{
srand(140142);
int n,m,i,j,k,root=1;
scanf("%d%d",&n,&low);
del(i=0);
tot=1;
for(i=1;i<=n;i++)
{
scanf("%s%d",str,&k);
switch(str[0])
{
case'I':if(k>=low) insert(root,k);
break;
case'A':treap[root].val+=k,treap[root].cov+=k;
break;
case'S':update(root,k); if(root==0) root=1;
break;
case'F':printf("%d\n",query(root,k));
break;
}
}
printf("%d",cnt-1);
return 0;
}