cf38g Queue (splay)

第一次写博客,莫名有些激动?讲真好好玩诶【捂脸】
以上是题外话 下面说正题【捂脸】
这里是题目
题意呢就是说有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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值