zoukankan      html  css  js  c++  java
  • POJ_2828_Buy Tickets

    题意:插队问题;

     2016.5.20,复习这道题。

    总结:线段树基础不牢,建树,更新尚不熟悉,注意加强理解记忆。

    主要理解:(单点更新,逆序插入)

    发生插队时,前面的队伍是连续没有空位的,即pos:2,1,这种情况不会出现,至少应该为pos:1,2,1

    插入顺序是逆序的(最后插入的val的位置不会再发生变化),如果正序插入则每个val的顺序是动态的。

    插入pos,那么在pos这个位置之前应该还有pos-1个空位。

    访问右节点的时候注意pos要修改,改为pos-sum[rt],即整个线段的第pos个空位,在下一个右儿子那的第pos-sum[rt]个空位。

    void Insert(int pos,int val,int l,int r,int rt)
    {
        if(l==r)
        {
            spare[rt]=0;
            seq[l]=val;
            return;
        }
        int mid=(r+l)>>1;
        if(pos<=spare[rt<<1])
            Insert(pos,val,l,mid,rt<<1);
        else
            Insert(pos-spare[rt<<1],val,mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    #define N 200005
    
    int spare[N<<2];
    int seq[N];
    
    void PushUp(int rt)
    {
        spare[rt]=spare[rt<<1]+spare[rt<<1|1];
    }
    
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            spare[rt]=1;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    
    void Insert(int pos,int val,int l,int r,int rt)
    {
        if(l==r)
        {
            spare[rt]=0;
            seq[l]=val;
            return;
        }
        int mid=(r+l)>>1;
        if(pos<=spare[rt<<1])
            Insert(pos,val,l,mid,rt<<1);
        else
            Insert(pos-spare[rt<<1],val,mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    
    int main()
    {
        int n,p[N],v[N];
        while(scanf("%d",&n)!=EOF)
        {
            build(1,n,1);
            int i;
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&p[i],&v[i]);
                p[i]++;
            }
            for(i=n;i>0;i--)
            {
                Insert(p[i],v[i],1,n,1);
            }
            for(i=1;i<=n;i++)
            {
                if(i!=n)
                    printf("%d ",seq[i]);
                else
                    printf("%d
    ",seq[i]);
            }
         /*for(i=1;i<=n;i++)         //如果这样输出就会超时,线段树容易超时
            {
           printf("%d",seq[i]); if(i!=n) printf(" "); else printf(" "); }*/
    } return 0; }

      

  • 相关阅读:
    Qt画笔实现折线图
    Qt动态布局
    ffmpeg录制流媒体,正常方式停止录制
    解决libvlc_media_player_stop时死锁的方法
    Ubuntu 16 修改时区!
    qt窗口最小化之后无法打开
    Qt 之 去除窗口部件被选中后的焦点虚线框
    WINDOWS中, 如何查看一个运行中的程序是64位还是32位的
    DHTMLX学习总结
    mui plus.uploader.createUpload 上传文件服务端获取文件名中文乱码问题
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/4732056.html
Copyright © 2011-2022 走看看