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;
}


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

相关文章推荐

hdu 3478 Catch【并查集+二分图染色】

Catch Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

FFT

ACM模版FFTconst double PI = acos(-1.0);// 复数结构体 struct Complex { double x, y; // 实部和虚部 x + yi...
  • f_zyj
  • f_zyj
  • 2016年07月05日 17:04
  • 922

POJ2828 Buy Tickets 【线段树】+【单点更新】+【逆序】

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 12296   A...

POJ 2828 Buy Tickets(线段树-单点更新)

点击打开链接 比较裸的线段树,主要在能不能想到(。ì _ í。) /* 思路: 设当前节点为root,其左孩子为lchild,右孩子为rchild,节点的存放变量为val,待插入数值为value....
  • Q_smell
  • Q_smell
  • 2017年04月07日 21:21
  • 102

poj(2828)——Buy Tickets(线段树维护点&点更新)

最近几天没怎么做线段树了,忙于消化新算法和比赛的题目。 正好比赛出了这道题,所以顺便做了这道题。 题目的大致意思: 现在有n个人,然后分别给出每个人所在的位置pos[i]与val[i],然后最后...

POJ - 2828 Buy Tickets(线段树单点更新)

题意: 有n个的排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍的某一个位置pos。要求把队伍最后的状态输出。 解析: 逆向思维。我们可以这样考虑,最后一个人一定会得到当前队伍...

POJ 2828 Buy Tickets (线段树单点更新)

Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 10957 Accepted: 5338 Descr...

poj 2828 Buy Tickets (线段树 单节点 查询位置更新)

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15533   Accepted: 775...
  • lsgqjh
  • lsgqjh
  • 2015年07月25日 11:34
  • 593

POJ 2828 Buy Tickets(单点更新)

题意:有n个的排队,每一个人都有一个val来对应,每一个后来人都会插入当前队伍的某一个位置pos。要求把队伍最后的状态输出。 逆向思维。我们可以这样考虑,最后一个人一定会得到当前队伍他想要的位置,如...

poj 2828 Buy Tickets 线段树

题意/Description:     Railway tickets were difficult to buy around the Lunar New Year in China, so we...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Poj 2828 Buy Tickets
举报原因:
原因补充:

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