hdu3436Queue-jumpers(splay+离散化)

来源:互联网 发布:dcp1618w扫描软件 编辑:程序博客网 时间:2024/06/06 14:05

题目请戳这里

题目大意:有一个队,n个人,编号1-n,有3种操作:

top x:将编号x的人放到队列首;

query x:查询编号x的人现在排在第几位;

rank x:查询现在第x位的人编号;

题目分析:splay。人数编号是10^8级别的,但是操作不超过10^5个,只需将top操作中的编号离散化就可以了,因为剩下的人都是连续的,所以将剩下的连续的人缩成一个点,只记录起始位置的人和连续长度即可。

trick:n可以为1,这种情况下,任何操作都是无意义的,遇到查询操作就输出1。。这点TLE出翔了。。。

感想:splay非常强大,但是如果不能1y,那就意味着悲剧。。。

详情请见代码:

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 200005;typedef __int64 ll;int hash[N];int add[N];int index[N];int next[N];struct spt{    int l,r,f,val,size,len;}tree[N];int n,m,q;struct node{    char cmd;    int x;}op[N];void init(){    for(int i = 0;i < N-10;i ++)        next[i] = i + 1;}int newnode(int st,int ed){    int p = next[0];    next[0] = next[p];    tree[p].l = tree[p].r = tree[p].f = 0;    tree[p].val = st;    tree[p].size = tree[p].len = ed - st;    return p;}void delnode(int p){    next[p] = next[0];    next[0] = p;}void del(int rt){    if(!rt)        return;    del(tree[rt].l);    del(tree[rt].r);    delnode(rt);}void pushup(int rt){    if(!rt)        return;    tree[rt].size = tree[tree[rt].l].size + tree[tree[rt].r].size + tree[rt].len;}void zig(int x){    int p = tree[x].f;    tree[p].l = tree[x].r;    if(tree[x].r)        tree[tree[x].r].f = p;    pushup(p);    tree[x].r = p;    tree[x].f = tree[p].f;    pushup(x);    tree[p].f = x;    if(tree[x].f == 0)        return;    if(tree[tree[x].f].l == tree[x].r)        tree[tree[x].f].l = x;    else        tree[tree[x].f].r = x;}void zag(int x){    int p = tree[x].f;    tree[p].r = tree[x].l;    if(tree[x].l)        tree[tree[x].l].f = p;    pushup(p);    tree[x].l = p;    tree[x].f = tree[p].f;    pushup(x);    tree[p].f = x;    if(tree[x].f == 0)        return;    if(tree[tree[x].f].l == tree[x].l)        tree[tree[x].f].l = x;    else        tree[tree[x].f].r = x;}int splay(int x,int goal){    while(tree[x].f != goal)    {        int p = tree[x].f;        int g = tree[p].f;        if(g == goal)        {            if(tree[p].l == x)                zig(x);            if(tree[p].r == x)                zag(x);        }        else        {            if(tree[g].l == p && tree[p].l == x)                zig(p),zig(x);            else if(tree[g].l == p && tree[p].r == x)                    zag(x),zig(x);                else if(tree[g].r == p && tree[p].l == x)                        zig(x),zag(x);                        else if(tree[g].r == p && tree[p].r == x)                                zag(p),zag(x);        }    }    pushup(x);    return x;}int build(int l,int r,int f){    if(l > r)        return 0;    int mid = (l + r)>>1;    int p = newnode(hash[mid],hash[mid + 1]);    tree[p].l = build(l,mid - 1,p);    tree[p].f = f;    tree[p].r = build(mid + 1,r,p);    pushup(p);    add[mid] = p;    return p;}int getfront(int rt){    while(tree[rt].l)    {        rt = tree[rt].l;    }    return rt;}int getval(int pos,int rt){    if(!rt)        return 0;    if(pos <= tree[tree[rt].l].size)        return getval(pos,tree[rt].l);    if(pos <= tree[tree[rt].l].size + tree[rt].len)        return rt;//pos - tree[tree[rt].l].size - 1 + tree[rt].val;    return getval(pos - tree[tree[rt].l].size - tree[rt].len,tree[rt].r);}int Bin(int x){    int l,r,mid;    l = 1;r = m;    while(r >= l)    {        mid = (l + r)>>1;        if(hash[mid] < x && hash[mid + 1] > x)            return mid;        if(hash[mid - 1] < x && hash[mid] > x)            return mid - 1;        if(hash[mid] == x)            return mid;        else if(hash[mid] > x)                r = mid - 1;            else                l = mid + 1;    }}void Top(int x,int &root){    int p = Bin(x);    root = splay(add[p],0);    if(tree[root].l == 0)    {        root = tree[root].r;        tree[root].f = 0;    }    else if(tree[root].r == 0)    {        root = tree[root].l;        tree[root].f = 0;    }    else    {//后继旋到右子树,左子树挂到右子树,删除根        int nt = getfront(tree[root].r);        tree[root].r = splay(nt,root);        tree[tree[root].l].f = tree[root].r;        tree[tree[root].r].l = tree[root].l;        tree[tree[root].r].f = 0;        root = tree[root].r;    }    pushup(root);    int tmp = getfront(root);    root = splay(tmp,0);    tree[root].l = add[p];    tree[add[p]].f = root;    tree[add[p]].l = tree[add[p]].r = 0;    root = splay(add[p],0);}void Query(int x,int &root){    int p = Bin(x);    root = splay(add[p],0);    int ans = tree[tree[root].l].size + x - tree[root].val + 1;    printf("%d\n",ans);}void Rank(int x,int &root){    int p = getval(x,root);    root = splay(p,0);    printf("%d\n",x - tree[tree[root].l].size - 1 + tree[root].val);}int main(){    int _,i,j;    int cas = 0;    char ss[10];    int root;    init();    scanf("%d",&_);    while(_--)    {       scanf("%d%d",&n,&q);        printf("n:%d q:%d\n",n,q);        j = 1;        printf("Case %d:\n",++cas);        if(n == 1)        {            for(i = 1;i <= q;i ++)            {                scanf("%s%d",ss,&j);                if(*ss == 'R' || *ss == 'Q')                    printf("1\n");            }            continue;        }        for(i = 1;i <= q;i ++)        {            scanf("%s",ss);            op[i].cmd = *ss;            scanf("%d",&op[i].x);            if(*ss == 'T')            {                hash[j] = op[i].x;                j ++;            }        }        sort(hash + 1,hash + j);        m = 2;        for(i = 2;i < j;i ++)            if(hash[i] != hash[i - 1])                hash[m ++] = hash[i];        for(i = 2,j = m;i < j;i ++)            if(hash[i] != hash[i - 1] + 1)                hash[m ++] = hash[i - 1] + 1;        if(hash[j - 1] < n)            hash[m ++] = hash[j - 1] + 1;        hash[m ++] = n + 1;        if(hash[1] != 1)            hash[m ++] = 1;        sort(hash + 1,hash + m);        m --;        root = build(1,m - 1,0);        for(i = 1;i <= q;i ++)        {            switch(op[i].cmd)            {            case 'T':Top(op[i].x,root);break;            case 'Q':Query(op[i].x,root);break;            case 'R':Rank(op[i].x,root);break;            }        }        del(root);    }    return 0;}//140MS4356K


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 摩托车被套牌了怎么办? 发现员工偷钱怎么办 盗窃刑事拘留7天怎么办 盗窃抓不到人怎么办 发现宿舍被盗后怎么办(  ) 发现宿舍被盗后怎么办() 回收到赃物电瓶怎么办 不知情买了赃物怎么办 盗窃单位要报警怎么办 上网吸烟被逮住怎么办 有人在微信骂我怎么办 网吧抽烟被拍照怎么办 诈骗被拘留该怎么办 行政拘留人跑了怎么办 车牌号被偷了怎么办 当员工提出辞职怎么办 老员工提出辞职怎么办 家人进看守所了怎么办 被贷款中介诈骗怎么办 喝完酒吐难受怎么办 犯罪嫌疑人死在看守所怎么办 犯罪嫌疑人死不承认怎么办 高血压进了看守所怎么办 看守所里被欺负怎么办 老师上课迟到了怎么办 艾滋病看守所不收怎么办 没能力偿还债务怎么办 监狱病人的癌症怎么办 监狱的传染病人怎么办 犯人在监狱重病怎么办 亲戚被关拘留所怎么办 打麻将被拘留怎么办 轻伤检察院不批捕怎么办 吸毒人被拘留怎么办 法院拘留没去怎么办 羁押期限超过了怎么办 羁押期限已满怎么办 刑事拘留22天了怎么办 被派出所拘留 车怎么办 被公安怀疑贩毒怎么办 报案后证据不足怎么办