浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html
浅谈\(fhq\)_\(treap\):https://www.cnblogs.com/AKMer/p/9981274.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1503
对于每个人都加工资,我们可以直接降低最低工资标准来判断,对于减工资,我们就加标准,那么每个人与最低标准的差值始终是正确的。
我们记一个\(now\)表示当前最低工资标准,记一个\(mn\)表示初始工资标准。那么每次进来一个工资为\(k\)的人,我们要使他与最低工资标准的差值是正确的,就应该使\(k\)加上\(now-mn\)。
而每个人与当前最低标准的差值加上初始标准,就是真实工资。
时间复杂度:\(O(nlogn)\)
空间复杂度:\(O(n)\)
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=1e5+5;
char s[25];
int n,mn,now,tot;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct Splay {
int tot,root;
int fa[maxn],son[maxn][2];
int siz[maxn],cnt[maxn],val[maxn];
int newnode(int v) {
val[++tot]=v;
siz[tot]=cnt[tot]=1;
return tot;
}
int find(int v) {
int u=root;
while(val[u]!=v) {
if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
}
return u;
}
int t(int u) {
return son[fa[u]][1]==u;
}
void update(int p) {
siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
}
void rotate(int u) {
int ret=t(u),f=fa[u],s=son[u][ret^1];
son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
fa[f]=u;update(f);update(u);
}
void splay(int u) {
while(fa[u]) {
if(fa[fa[u]]) {
if(t(fa[u])==t(u))rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
root=u;
}
void ins(int v) {
if(!root) {root=newnode(v);return;}
int u=find(v);
if(val[u]==v) {siz[u]++;cnt[u]++;splay(u);return;}
fa[newnode(v)]=u;son[u][v>val[u]]=tot;
splay(tot);
}
void check() {
int u=find(now);splay(u);
if(val[u]<now) {
u=son[u][1];
while(son[u][0])u=son[u][0];
splay(u);
}
fa[son[u][0]]=0;
son[u][0]=0;update(u);
}
int get_val(int k) {
int u=root,rk=siz[u]-k+1;
if(rk<1)return -1;
while(rk) {
if(siz[son[u][0]]>=rk)u=son[u][0];
if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
}
return val[u]+mn-now;
}
}T;
int main() {
n=read(),now=mn=read();
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
int k=read();
if(s[1]=='I') {
k+=now-mn;
if(k<now)continue;
T.ins(k);tot++;
}
if(s[1]=='A')now-=k;
if(s[1]=='S') {
now+=k;
T.check();
}
if(s[1]=='F')printf("%d\n",T.get_val(k));
}
printf("%d\n",tot-T.siz[T.root]);
return 0;
}
#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
const int maxn=1e5+5;
char s[25];
int n,m,tot,mn,now;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct fhq_treap {
int tot,root;
int fix[maxn],son[maxn][2];
int siz[maxn],cnt[maxn],val[maxn];
int newnode(int v) {
val[++tot]=v;fix[tot]=rand();
siz[tot]=cnt[tot]=1;return tot;
}
int getkth(int u,int v,bool &bo,int delta) {
if(!u)return 0;int ans=0;
if(val[u]>v)ans=getkth(son[u][0],v,bo,delta);
else if(val[u]==v) {
if(delta)cnt[u]+=delta,siz[u]+=delta,bo=1;
return siz[son[u][0]];
}
else ans=siz[son[u][0]]+cnt[u]+getkth(son[u][1],v,bo,delta);
if(bo)siz[u]+=delta;return ans;
}
void update(int p) {
siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
}
pii split(int u,int rk) {
if(!rk)return make_pair(0,u);
if(rk==siz[u])return make_pair(u,0);
if(siz[son[u][0]]>=rk) {
pii tmp=split(son[u][0],rk);
son[u][0]=tmp.second,update(u);
return make_pair(tmp.first,u);
}
else {
pii tmp=split(son[u][1],rk-siz[son[u][0]]-cnt[u]);
son[u][1]=tmp.first,update(u);
return make_pair(u,tmp.second);
}
}
int merge(int a,int b) {
if(!a||!b) return a+b;
if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),update(a),a;
else return son[b][0]=merge(a,son[b][0]),update(b),b;
}
void ins(int v) {
bool bo=0;int rk=getkth(root,v,bo,1);
if(bo)return;pii tmp=split(root,rk);
root=merge(merge(tmp.first,newnode(v)),tmp.second);
}
void check() {
bool bo=0;
int rk=getkth(root,now,bo,0);
pii tmp=split(root,rk);root=tmp.second;
}
int get_val(int k) {
int u=root,rk=siz[u]-k+1;
if(rk<1)return -1;
while(rk) {
if(siz[son[u][0]]>=rk)u=son[u][0];
if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
}
return val[u]+mn-now;
}
}T;
int main() {
srand(time(0));
n=read(),now=mn=read();
for(int i=1;i<=n;i++) {
scanf("%s",s+1);int k=read();
if(s[1]=='I') {
k+=now-mn;
if(k<now)continue;
T.ins(k);tot++;
}
if(s[1]=='A')now-=k;
if(s[1]=='S') {
now+=k;
T.check();
}
if(s[1]=='F')printf("%d\n",T.get_val(k));
}
printf("%d\n",tot-T.siz[T.root]);
return 0;
}
原文:https://www.cnblogs.com/AKMer/p/9991772.html