【HDU 3436】Queue-jumpers(Splay)

Splay的基础操作。问题的关键就在于N非常大,就算是利用Splay数组也是远远开不下的,因此很自然地想到了hash一下

可以将所有要进行Top的节点和Query的节点

然后对于每一个节点或者每一个段,可以将它的长度表示出来(方便起见每个点可以看做一个长度为1的线段)

剩下的就是Splay的基础操作了

1、top:将节点删除后插入到队首

2、Rank:找到当前子树的第k个数

3、Query:询问第k个人的位置。可以将该点旋转至树根,那么左子树的个数+1就是其位置

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN = 200025;
int txt = 1;
int has[SIZEN],cntx;
int n_val[SIZEN];
int p[SIZEN>>1];
char op[SIZEN>>1];
int read(){
    char ch = ' ';
    while(ch < '0' || ch > '9') ch = getchar();
    int ans = 0;
    while(ch <= '9' && ch >='0'){
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
    }
    return ans;
}
struct SplayTree{
    int ch[SIZEN][2];
    int pre[SIZEN];
    int sz[SIZEN];
    int top,root;
    inline void pushup(int x){
        sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + cnt[x];
    }
    int Newnode(int x){
        pre[x] = ch[x][0] = ch[x][1] = 0;
        cnt[x] = sz[x] = n_val[x + 1] - n_val[x];
        return x;
    }
    void debug(){
        printf("root:%d\n",root);
        Travel(root);
    }
    void Travel(int x){
        if(ch[x][0]) Travel(ch[x][0]);
        printf("node:%d lson:%d rson:%d pre:%d sz:%d cnt:%d val:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],cnt[x],n_val[x]);
        if(ch[x][1]) Travel(ch[x][1]);
    }
    inline void Rotate(int x,int f){
        int y = pre[x];
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(pre[y]) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x;
        ch[x][f] = y;
        pre[y] = x;
        pushup(y);
    }
    inline void Splay(int x,int goal){
        while(pre[x] != goal){
            if(pre[ pre[x] ] == goal)
                Rotate(x,ch[ pre[x] ][0] == x);
            else{
                int y = pre[x],z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x){
                    Rotate(x,!f),Rotate(x,f);
                }
                else{
                    Rotate(y,f),Rotate(x,f);
                }
            }
        }
        pushup(x);
        if(goal == 0) root = x;
    }
    inline void build(int &x,int l,int r,int f){
        if(l > r) return;
        int mid = (l + r) >> 1;
        x = Newnode(mid);
        build(ch[x][0],l,mid - 1,x);
        build(ch[x][1],mid + 1,r,x);
        pre[x] = f;
        pushup(x);
    }
    inline void init(){
        ch[0][0] = ch[0][1] = pre[0] = 0;
        sz[0] = cnt[0] = 0;
        root = top = 0;
    }
    int findmax(int x){
        while(ch[x][1]){
            x = ch[x][1];
        }
        return x;
    }
    int findmin(int x){
        while(ch[x][0]){
            x = ch[x][0];
        }
        return x;
    }
    inline void del(int x){
        Splay(x,0);
        if(ch[x][0] == 0){
            root = ch[x][1];
            ch[x][0] = ch[x][1] = pre[x] = 0;
            pre[root] = 0;
            return;
        }
        int m = findmax(ch[root][0]);
        Splay(m,root);
        ch[m][1] = ch[x][1];
        ch[x][0] = ch[x][1] = 0;
        pre[x] = 0;
        pre[ ch[m][1] ] = m;
        root = m;
        pre[root] = 0;
        pushup(root);
    }
    inline void query(int i){
        int loc = p[i];
        loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1;
        Splay(loc,0);
        printf("%d\n",sz[ ch[root][0] ] + 1);
    }
    inline void Top(int i){
        int loc = p[i];
        loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1;
        del(loc);
        if(root == 0){
            root = loc;
            ch[root][0] = ch[root][1] = 0;
            pre[root] = 0;
            return;
        }
        int Min = findmin(root);
        Splay(Min,0);
        ch[root][0] = loc;
        pre[loc] = root;
        ch[loc][0] = ch[loc][1] = 0;
        pushup(loc);
        pushup(root);
        Splay(loc,0);
    }
    inline int getrank(int x,int k){
        int t = sz[ ch[x][0] ];
        if(t >= k)
            return getrank(ch[x][0],k);
        else if(k <= t + cnt[x])
            return n_val[x] + k - t - 1;
        else
            return getrank(ch[x][1],k - t - cnt[x]);
    }
    inline void rank(int i){
        int k = p[i],loc;
        printf("%d\n",getrank(root,k));
    }
    int cnt[SIZEN];
};
SplayTree spt;
void Has(int &cnt,int n){
    has[cnt++] = n + 1;has[cnt++] = 1;
    has[cnt++] = 0;
    sort(has,has+cnt);
    int ncnt = 0;
    n_val[ncnt++] = has[0];
    for(int i=1;i<cnt;i++){
        if(has[i] != has[i - 1]){
            if(has[i - 1] + 1 != has[i])
                n_val[ncnt++] = has[i - 1] + 1;
            n_val[ncnt++] = has[i];
        }
    }
    cnt = ncnt;
}

void solve(){
    int n,q;
    char t_op[10];
    scanf("%d%d",&n,&q);
    printf("Case %d:\n",txt++);
    spt.init();
    cntx = 0;
    has[cntx++] = 0;
    for(int i=0;i<q;i++){
        scanf("%s",t_op);
        p[i] = read();
        op[i] = t_op[0];
        if(op[i] != 'R') has[cntx++] = p[i];
    }
    Has(cntx,n);
    spt.build(spt.root,1,cntx - 2,0);
    spt.pushup(spt.root);
    for(int i=0;i<q;i++){
        if(op[i] == 'T') spt.Top(i);
        else if(op[i] == 'R') spt.rank(i);
        else if(op[i] == 'Q') spt.query(i);
    }
}
int main()
{
    //freopen("data.in","r",stdin);
    int _;
    scanf("%d",&_);
    while(_--) solve();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值