第一次写博客,莫名有些激动?讲真好好玩诶【捂脸】
以上是题外话 下面说正题【捂脸】
这里是题目
题意呢就是说有n个人,每个人有一个重要度ai和一个良心值ci,每次他先来到队尾如果比前一个人重要度高且良心值不为0,那么他们两个人就会换位置并且良心值减一,问最终的排队方式。
也就是说,每个人i换到的位置有两种可能,第一种也就是队伍中从后往前第一个比他的重要度大,第二种就是按位置来说的i-ci。在这两种中找到一个靠后的。那就维护一个splay按照队伍中的位置建,每次找第一个比ai大的的下一个,假如可以换到那就加入这个点;不然就找到能换到的那个,在他前面加入这个点
代码丑【捂脸】
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 110000
int size[N],mx[N],v[N],fa[N],ch[N][2],num[N],tot=0,root=0,n,nn;
void update(int p){
size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
mx[p]=max(mx[ch[p][0]],v[p]);mx[p]=max(mx[p],mx[ch[p][1]]);
}
void rotate(int &x){
int y=fa[x],z=fa[y],t=ch[y][0]==x;
if(z) ch[z][ch[z][1]==y]=x;
else root=x;
fa[y]=x;fa[x]=z;fa[ch[x][t]]=y;
ch[y][t^1]=ch[x][t];ch[x][t]=y;
update(y);update(x);
}
void splay(int x,int &rt){
while(x!=rt){
int y=fa[x];
if(y==rt){rotate(x);return;}
if(ch[y][0]==x^ch[fa[y]][0]==y) rotate(x);
else rotate(y);rotate(x);
}
}
void insert(int x,int y,int z){
splay(x,root);
int succ=ch[x][1];
while(ch[succ][0]) succ=ch[succ][0];
splay(succ,ch[x][1]);
ch[succ][0]=++tot;size[tot]=1;v[tot]=mx[tot]=y;num[tot]=z;fa[tot]=succ;ch[tot][0]=ch[tot][1]=0;
update(succ);update(x);
}
int qmax(int p,int x){//找到第一个比ai大的,顺便记录位置nn
if(v[p]>x && x>mx[ch[p][1]]) {nn+=size[ch[p][0]]+1;return p;}
if(x>mx[ch[p][1]]) return qmax(ch[p][0],x);
nn+=size[ch[p][0]]+1;return qmax(ch[p][1],x);
}
int query(int p,int x){//找到队伍中最后能换到的那个人
if(size[ch[p][0]]+1==x) return p;
if(x<=size[ch[p][0]]) return query(ch[p][0],x);
return query(ch[p][1],x-size[ch[p][0]]-1);
}
void print(int p){
if(ch[p][0]) print(ch[p][0]);
if(p>2) printf("%d ",num[p]);
if(ch[p][1]) print(ch[p][1]);
}
int main(){
freopen("a.in","r",stdin);
int x,y;scanf("%d",&n);
root=1;tot=2;
v[1]=mx[1]=num[1]=n+1;size[1]=2;fa[1]=0;ch[1][0]=0;ch[1][1]=2;
v[2]=mx[2]=num[2]=0;size[2]=1;fa[2]=1;ch[2][0]=ch[2][1]=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&x,&y);nn=0;
int l=qmax(root,x);
if(i-y<=nn) insert(l,x,i);
else{
l=query(root,i-y);
insert(l,x,i);
}
}print(root);
return 0;
}