zoukankan      html  css  js  c++  java
  • P3285 [SCOI2014]方伯伯的OJ

    https://www.luogu.org/problemnew/show/P3285

    题目描述

    方伯伯正在做他的Oj。现在他在处理Oj上的用户排名问题。Oj上注册了n个用户,编号为1~n“,一开始他们按照编号排名。

    方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号:

    1.操作格式为1 x y,意味着将编号为x的用户编号改为y,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时,1是一个当前不在排名中的编号。

    2.操作格式为2 x,意味着将编号为x的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为x用户的排名。

    3.操作格式为3 x,意味着将编号为x的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为x用户的排名。

    4.操作格式为4 k,意味着查询当前排名为k的用户编号,执行完该操作后需要输出当前操作用户的编号。

    但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了:

    • 1 x+a y+a
    • 2 x+a
    • 3 x+a
    • 4 k+a
    • 其中a为上一次操作得到的输出,一开始a=0。

    例如:上一次操作得到的输出是5这一次操作的输入为:1 13 15因为这个输入是经过加密后的,所以你应该处理的操作是1 8 10现在你截获了方伯伯的所有操作,希望你能给出结果。

    输入输出格式

    输入格式:

    输入的第1行包含2个用空格分隔的整数n和m,表示初始用户数和操作数。此后有m行,每行是一个询问,询问格式如上所示。

    输出格式:

    输出包含m行。每行包含一个整数,其中第i行的整数表示第i个操作的输出。

    输入输出样例

    输入样例
    10 10
    1 2 11
    3 13
    2 5
    3 7
    2 8
    2 10
    2 11
    3 14
    2 18
    4 9
    输出样例
    2
    2
    2
    4
    3
    5
    5
    7
    8
    11

    说明

    对于 100% 的数据,1 <= n <= 10^8,1 <= m <= 10^5

    输入保证对于所有的操作 1,2,3,x 必然已经出现在队列中,同时对于所有操作 1,1 <= y <= 2 * 10^8,并且

    y 没有出现在队列中。

    对于所有操作 4,保证 1 <= k <= n。

    动态开点线段树?

      利用线段树维护序列的整体顺序,然后建立元素编号与其所在线段树位置的双映射(可以用 hash )。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100500000;
    int n,m,opt,x,y;
    int ans,L,R,root;
    int sum[10000000],cnt;
    int son[10000000][2];
    struct node
    {
        int tot;
        int head[1000000];
        int nex[1000000];
        int rea[1000000];
        int val[1000000];
        void add(int u,int v)
        {
            int has=u%999997;
            ++tot;
            nex[tot]=head[has];
            head[has]=tot;
            rea[tot]=u;
            val[tot]=v;
        }
        int ask(int u)
        {
            for(int i=head[u%999997];i;i=nex[i])
                if(rea[i]==u)
                    return val[i];
            return 0;
        }
    }pos,rpos;
    void calc_ask(int &u,int l,int r,int v)
    {
        if(!u)    u=++cnt;
        if(l==r)
        {
            ++ans;
            return ;
        }
        int mid=(l+r)>>1;
        int tmp=max(0,min(R,mid)-max(L,l)+1-sum[son[u][0]]);
        if(v<=mid)    calc_ask(son[u][0],l,mid,v);
        else
        {
            ans+=tmp;
            calc_ask(son[u][1],mid+1,r,v);
        }
    }
    void calc_add(int &u,int l,int r,int v)
    {
        if(!u)    u=++cnt;
        ++sum[u];
        if(l==r)    return ;
        int mid=(l+r)>>1;
        if(v<=mid)    calc_add(son[u][0],l,mid,v);
        else    calc_add(son[u][1],mid+1,r,v);
    }
    void calc_kth(int &u,int l,int r,int v)
    {
        if(l==r)
        {
            ans=rpos.ask(l);
            if(!ans)    ans=l-m;
            return ;
        }
        int mid=(l+r)>>1;
        int tmp=max(0,min(R,mid)-max(L,l)+1-sum[son[u][0]]);
        if(v<=tmp)    calc_kth(son[u][0],l,mid,v);
        else    calc_kth(son[u][1],mid+1,r,v-tmp);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        L=m+1;R=n+m;
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&opt,&x);
            if(opt==1)    scanf("%d",&y);
            x-=ans;y-=ans;ans=0;
            if(opt==1)
            {
                int tmp=pos.ask(x);
                if(!tmp)    tmp=x+m;
                calc_ask(root,1,N,tmp);
                pos.add(y,tmp);
                rpos.add(tmp,y);
            }
            else if(opt==2)
            {
                int tmp=pos.ask(x);
                if(!tmp)    tmp=x+m;
                calc_ask(root,1,N,tmp);
                calc_add(root,1,N,tmp);
                pos.add(x,--L);
                rpos.add(L,x);
            }
            else if(opt==3)
            {
                int tmp=pos.ask(x);
                if(!tmp)    tmp=x+m;
                calc_ask(root,1,N,tmp);
                calc_add(root,1,N,tmp);
                pos.add(x,++R);
                rpos.add(R,x);
            }
            else
                calc_kth(root,1,N,x);
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    APP的LOGO设计需求
    App 中使用 Iconfont 的整套方案
    UI流程总结
    sketch制作LOGO(一)---环形光晕
    Sketch插件--Rename It
    Sketch Measure使用教程
    04 流程控制
    03 python语法注释、用户交互、格式化输出、基本数据类型、运算符
    02编程语言及python初识
    第一课
  • 原文地址:https://www.cnblogs.com/wyher/p/10296997.html
Copyright © 2011-2022 走看看