• 线段树端点更新 poj 2828 Buy Tickets


    题目链接:

    http://poj.org/problem?id=2828

    题目意思:

    有n个人排队,每个人有个pos值,和value值,表示他可以插到第pos个人的后面,输出最后的队形序列。

    解题思路:

    如果顺着插的话,要移动后面的队列,如果用链表的话,找到插入的位置很费时。

    如果逆着考虑的话,当前的人插到恰好有pos个空位的最小的地方,就很简单。

    用线段树维护区间内空位的个数,如果要求的空位数大于左边区间的空位数,则减去左边的空位数,再在右边查找。

    总结:抽象出线段树维护的空间很重要。

    代码:

    //如果逆着推的话,就不用移动很多元素了,这是关键,
    //用线段树维护区间的空位数,如果左边的空位数不够的话,选择右边(其中把左边占满),知道找到插入的位置
    //线段树 抽象出维护的空间 很关键
    
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<stack>
    #include<list>
    #include<queue>
    #define eps 1e-6
    #define INF (1<<30)
    #define PI acos(-1.0)
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define maxn 210000
    
    int sum[maxn*4];
    int pos[maxn],value[maxn],ans[maxn],n;
    int temp;
    /*
    freopen("data.in","r",stdin);
    freopen("data.out","w",stdout);
    */
    void build(int l,int r,int rt)
    {
        sum[rt]=r-l+1; //初始区间空位的多少
        if(r==l)
            return ;
        int m=(l+r)>>1;
    
        build(lson);
        build(rson);
    }
    
    void update(int target,int l,int r,int rt)
    {
        sum[rt]--;   //所到之处,空位数减一,因为必须在某个区间插
        if(l==r)
        {
            temp=l; //找到空位的位置,记住然后进行插入
            return ;
        }
    
        int m=(l+r)>>1;
    
        if(target<=sum[rt<<1])  //如果左区间的空位数够的话,在左区间更新
            update(target,lson);
        else
            update(target-sum[rt<<1],rson); //左区间不够,先把左区间占满,然后在填右区间
        return ;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++)
                scanf("%d%d",&pos[i],&value[i]);
            build(1,n,1);
    
            for(int i=n;i>=1;i--)
            {
                update(pos[i]+1,1,n,1);
                ans[temp]=value[i];  //把位置找到然后插入
            }
            printf("%d",ans[1]);
            for(int i=2;i<=n;i++)
                printf(" %d",ans[i]);
            putchar('\n');
        }
        return 0;
    }
    
    


     

  • 相关阅读:
    用数据泵技术实现逻辑备份Oracle 11g R2 数据泵技术详解(expdp impdp)
    用mysql实现类似于oracle dblink的功能
    统计1的个数
    转置字符串,其中单词内的字符需要正常
    经典排序之归并排序
    公共子序列与公共子串问题
    placement new (转)
    数组排序组合最小数字
    实现两个数相加不用四则运算
    操作系统中作业、线程、进程、内存管理、垃圾回收以及缓存等概念
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2999168.html
Copyright © 2020-2023  润新知