• poj2828 Buy Tickets ***


    线段树

    //2828

    View Code
    /*
    * [这段话转的。。]
    * 如果我们从头开始一次做的话,无论是用链表还是数组,肯定会超时(链表寻址时间长,数组移位时间长。)。
    * 所以要用一个快速的方法直接找到位置。但是换个角 度,如果我们反过来排,那样的话,我们就知道他所在的
    * 精确位置!把存储的结构想象成是链表,插队的人插入后,把他所在的位置从链表中屏蔽掉,然后在新的链 表种
    * 继续这样存,这样的话我们就得到了我们想要的顺序!
    *
    * 按照这种思想,可以用线段树实现。。。
    *
    */

    #include
    <cstdio>
    using namespace std;

    const int MAXN = 200000 + 5;
    int n, p[MAXN], v[MAXN];
    int ans[MAXN], tail;

    struct node{
    int l, r;
    int num, value; //num:当前时刻,该区间有多少空位,, value:该区间的人的value(只叶子节点有意义)
    };
    node tree[MAXN
    * 3]; //注意*3! 否则 RE!!

    //建树
    void build(int i, int l, int r){
    tree[i].l
    = l; tree[i].r = r;
    tree[i].num
    = r - l + 1; //初始时的空位数

    if(l == r) return;
    int mid = (l + r) >> 1;
    build(i
    <<1, l, mid);
    build(i
    <<1 | 1, mid+1, r);
    }

    //……
    void insert(int i, int p, int v){
    tree[i].num
    --; //没到一个区间,该区间的空位数-1,
    // 因为既然到达该区间,则该人要么在该区间,要么在该区间的子区间。都导致区间的空位数-1

    if(tree[i].l == tree[i].r){ //只叶子节点的value有意义
    tree[i].value = v;
    return ;
    }

    if(tree[i<<1].num > p)
    insert(i
    <<1, p, v);
    else
    insert(i
    <<1 | 1, p-tree[i<<1].num, v); //减去左子区间的空位数
    }

    void cal(int i){
    if(tree[i].l == tree[i].r){
    ans[tail
    ++] = tree[i].value;
    return;
    }
    cal(i
    <<1);
    cal(i
    <<1 | 1);

    }

    int main(){
    while(scanf("%d", &n) == 1){
    for(int i=0; i<n; i++)
    scanf(
    "%d %d", &p[i], &v[i]);

    build(
    1, 1, n);

    for(int i=n-1; i>=0; i--){
    insert(
    1, p[i], v[i]);
    }

    tail
    = 0;
    cal(
    1);

    printf(
    "%d", ans[0]);
    for(int i=1; i<n; i++){
    printf(
    " %d", ans[i]);
    }
    printf(
    "\n");

    }

    return 0;
    }

    也可以用树状数组

    【转】

    View Code
    /*
    PKU 2828:树状数组+二分,一开始一直在想如何处理后面加进来的人,即正着考虑的话,当前的信息是不能得到答案的,突然想起以前一道题,发现只要倒着处理的话,就能很好得解决这个问题了,因为最后一个插进来的人所插入的位置就是这个人最后所站的位置。具体的做法就是先在树状数组的每个位置上都加1,表示一开始每个位置上都站着一个人,每次二分查找该人所站的位置,找到后把这个位置的1减掉,相当于这个位置被占据了,那么下次要得到相同人数的话位置就相应得往后移了。
    */
    #include
    <cstdio>
    #include
    <memory.h>
    using namespace std;

    const int N = 200005;
    int _n;
    int res[N];
    int c[N];
    struct Peo {
    int pos, val;
    }peo[N];

    int lowbit( int n )
    {
    return n & (-n);
    }

    void modify( int n, int delta )
    {
    while( n <= _n )
    {
    c[n]
    += delta;
    n
    += lowbit(n);
    }
    }

    int sum( int n )
    {
    int ret = 0;
    while( n != 0 )
    {
    ret
    += c[n];
    n
    -= lowbit(n);
    }
    return ret;
    }

    int getRank( int pos ) {
    int mid, begin = 1, end = _n;
    while ( begin < end ) {
    mid
    = (begin + end) / 2;
    if ( sum(mid) >= pos ) end = mid;
    else begin = mid + 1;
    }
    return end;
    }

    int main()
    {
    while ( scanf("%d", &_n) != EOF ) {
    int i;
    memset(c,
    0, sizeof(c));
    for (i=1; i<=_n; ++i) {
    scanf(
    "%d %d", &peo[i].pos, &peo[i].val);
    peo[i].pos
    ++;
    modify(i,
    1);
    }
    for (i=_n; i>=1; --i) {
    int now = getRank(peo[i].pos);
    res[now]
    = peo[i].val;
    modify(now,
    -1);
    }
    for (i=1; i<_n; ++i) {
    if (i == 1) printf("%d", res[i]);
    else printf(" %d", res[i]);
    }
    printf(
    " %d\n", res[_n]);
    }
    return 0;
    }
  • 相关阅读:
    第二阶段冲刺第二天
    第二阶段冲刺第一天
    第十四周学习进度条
    《探索需求-设计前的质量》阅读笔记六
    《探索需求-设计前的质量》阅读笔记五
    xxx征集系统项目目标文档
    《探索需求-设计前的质量》阅读笔记四
    《探索需求-设计前的质量》阅读笔记三
    将一台电脑上的虚拟机上的系统复制到另一台电脑的虚拟机上!!!and想询问大神们问题的解决办法??
    《探索需求-设计前的质量》阅读笔记二
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2102395.html
Copyright © 2020-2023  润新知