Poj 2828 Buy Tickets

原创 2015年11月19日 14:55:56

一个线段树加点思维的题目

被窝用splay水过去了Orz

(其实我也不想的,只是正好刚学splay,就看到一个动态插入的题,就。。。就没忍住Orz


用splay写就不用什么思维了,我的思路是给这个队列加上一个虚拟的最后一人来处理刚开始一个人都没有的时候插入的情况

这样写还可以在之后插入的时候无脑插在左边,不用担心没有右边的节点的情况,大概就酱


以及代码如下


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define l ch[0]
#define r ch[1]

struct node{
    int val,siz;
    node * ch[2];
    void maintain(){
        siz = 1;
        if(l) siz+=l->siz;
        if(r) siz+=r->siz;
    }
};

int siz(node * o){
    if(!o)
        return 0;
    return o->siz;
}

const int maxn = 212345;

node nodes[maxn];
int tot;

void out(node * rot,int d,int k){
    if(rot->r)
        out(rot->r,d+1,-1);
    for(int i=0;i<d;i++)
        printf("  ");
    if(k==0)
        printf("--");
    else{
        if(k==-1) printf("/");
        else printf("\\");
    }
    printf("%d ( %d )\n",rot->val,rot->siz);
    if(rot->l)
        out(rot->l,d+1,1);
}

void print(node * root){
    out(root,0,0);
}

node * newnode(int x){
    node * ret = &nodes[tot++];
    ret->val = x;
    ret->siz = 1;
    ret->l=ret->r=NULL;
    return ret;
}

void zg(node* &o,int d){
    node * k = o->ch[d];
    o->ch[d]=k->ch[d^1];
    k->ch[d^1]=o;
    o=k;
    o->maintain();
    o->ch[d^1]->maintain();
}

int splay(node* &rot,int x){
    int p = siz(rot->l)+1;
    if(p==x)
        return 2;
    int d = p > x ? 0 : 1;
    if(d) x-=p;
    int k = splay(rot->ch[d],x);
    if(k==2)
        return d;
    if(k==d) zg(rot,k);
    else zg(rot->ch[d],k);
    zg(rot,d);
    return 2;
}

void fnd(node* &rot,int x){
    int k = splay(rot,x);
    if(k!=2)
        zg(rot,k);
}

void inser(int val,int lo,node* &root){
    node * k = newnode(val);
    lo++;
    if(lo==1){
        fnd(root,1);
        root->l = k;
        root->maintain();
    }
    else{
        fnd(root,lo-1);
        fnd(root,lo);
        root->l->r = k;
        root->l->maintain();
        root->maintain();
    }
}

int ans[maxn];
int len;

void mid(node *rot){
    if(rot->l)
        mid(rot->l);
    ans[len++]=rot->val;
    if(rot->r)
        mid(rot->r);
}


int main(){
    int n;
    while(~scanf("%d",&n)){
        tot = 0;
        node *rot = newnode(0);
        int x,pos;
        for(int i=1;i<=n;i++){
            scanf("%d %d",&pos,&x);
         //   print(rot);
            inser(x,pos,rot);
        }
        len = 0;
        mid(rot);
        for(int i=0;i<n;i++)
            printf(i<n-1?"%d ":"%d\n",ans[i]);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Poj 2892 Tunnel Warfare

一段区间上有一段连续的房子,每次可以消灭一个房子,修复一个房子,询问某一个房子所在的区间的长度 一个简单的线段树题 用splay写的话也很简单的,因为能正好对应splay的一些基本操作 ...

Linux操作系统下查找大文件或目录的技巧

Linux操作系统下查找大文件或目录的技巧

【01trie合并】hdu 6191

一道广西邀请赛的题,赛场上想到了trie合并,但是没写过,算不清时间复杂度。于是迟迟没下去手 下来之后瞅了瞅感觉很简单啊,用递归+指针写了写,结果MLE+RE到绝望。 最后改成了非递归终于...

HDU 3487 Play with Chain (Splay tree)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 再撸一发Spl...

Splay树(区间添加删除 | 区间翻转)——HDU 3487 Play with Chain

Splay树——HDU 3487 Play with Chain

HDU3487(splay区间翻转+区间切割)

F - Play with Chain Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d &am...

bzoj1251 序列终结者

不错的伸展树入门题查询区间最大值,支持区间加一个值,区间翻转区间更新的时候像线段树一样打一个标记就好值得注意的一点是,虽然这是自底而上伸展的代码,但是该节点的祖先节点的lazy标记在zig/zag的过...

s blazebank doesn&rsquo

How to Make Your Adjustment of the Sac24559503b5c84d0f57d66b1893bed4adduce Antenna and Dburrowbox Mo...

HDU 1890 Robotic Sort 伸展树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1890题意:给定一个数列,数列中的元素可能重复,给这个数列排序,输出每次排序时第i个数所在的位置。保持相等元...

伸展树模板

给定一个数n,代表有一个数列1~n,有下面两种操作: CUT a b c 把区间[a,b]这一段元素切下来接到第c个元素的后面 FLIP a b 反转区间[a,b] //其中有一些与本题无关的代码...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)