算法
这个题有一个对于全体的修改。
考虑[NOIP2016]蚯蚓
那个做法,维护一个变量add
即可。
那么本题还需要以下操作:
- 插入。考虑到
add
,需要把k
减去add
后再插入。 - 删除小于k的所有节点。这个直接按
k-1
的权值分裂即可。同样要考虑add
,所以实际上删除的是小于min-add
的节点。而且删除时还要统计删除的节点个数。
然后就可以氵掉这个题。
代码
#include <bits/stdc++.h>
#define re register
using namespace std;
inline int read() {
int X=0,w=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
while (c>='0'&&c<='9') X=(X<<3)+(X<<1)+c-'0',c=getchar();
return X*w;
}
const int MAXN=100010;
int ans=0;
struct fhq_treap {
int ch[MAXN][2];
int sz[MAXN],val[MAXN],rnd[MAXN];
int root,cnt;
fhq_treap() { root=cnt=0; }
inline void init() { root=cnt=0; }
inline void pushup(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; }
inline int new_node(int x) { sz[++cnt]=1,val[cnt]=x,rnd[cnt]=rand(); return cnt; }
inline void split(int now,int k,int& x,int& y) {
if (!now) { x=y=0; return; }
if (val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);
else y=now,split(ch[now][0],k,x,ch[now][0]);
pushup(now);
}
inline int merge(int A,int B) {
if (!A||!B) return A+B;
if (rnd[A]<rnd[B]) { ch[A][1]=merge(ch[A][1],B); pushup(A); return A; }
else { ch[B][0]=merge(A,ch[B][0]); pushup(B); return B; }
}
inline int kth(int k) {
int now=root;
while (1) {
if (k<=sz[ch[now][1]]) now=ch[now][1];
else if (k==sz[ch[now][1]]+1) return now;
else k-=sz[ch[now][1]]+1,now=ch[now][0];
}
}
inline void insert(int k) {
int x,y; split(root,k,x,y);
root=merge(merge(x,new_node(k)),y);
}
inline void del(int k) { //删除小于k的数
int x,y; split(root,k-1,x,y);
ans+=sz[x]; root=y;
}
inline void query(int k,int add) {
if (k>sz[root]) puts("-1");
else printf("%d\n",val[kth(k)]+add);
}
};
fhq_treap T;
int main() {
int add=0;
int n=read(),Min=read();
while (n--) {
char op=getchar();
while (!isalpha(op)) op=getchar();
int k=read();
if (op=='I'&&k>=Min) T.insert(k-add);
else if (op=='A') add+=k;
else if (op=='S') { add-=k; T.del(Min-add); }
else if (op=='F') T.query(k,add);
}
printf("%d\n",ans);
return 0;
}
菜鸡表示一个地方写错调了好久qwq