• 线段树专辑 —— pku 2828 Buy Tickets


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

    灰常有趣的一道逆序思维题目,并且题目掐的很死,用链表什么的,统统tle

    如何逆序思维?假设数据如下:

    4
    0 77
    1 51
    1 33
    2 69

    我们从后向前解题,开始是第四个人,他的pos==2,可是他前面分明还有3个人,也就是说,他必须插一个人的队才有可能达到他要达到的位置

    再看第三个人,他的pos==1,他前面还有两人,他也需要插一个队

    再看第二个人,他的pos==1,前面也只有一个人,1-1==0,他不需要插队

    第一个人,0-0==0,也不需要插队了

    最终队序是:

    77 33 69 51
    
    

    我们用线段树加快插队速度,如何做?很简单,定义一个left表示该区间剩余的容量,假如要插入第w个位置,那么我们便从tree[1]开始向下查找,如果左子区间的left>=w,那么便向左区间递归下去,否则则向右子区间递归查找w-tree[2*i].left位置。如此这般,直到找到了叶子节点。

    这里要注意一下顺序,第一个叶子节点表示的意思是插0个队的位置,第二个叶子节点表示的是插一个队的位置。。。。所以最后输出的时候记得倒过来输出

     

    View Code
     1 #include<iostream>
    2 #include<string>
    3 using namespace std;
    4
    5 struct node
    6 {
    7 int l;
    8 int r;
    9 int left;
    10 };
    11
    12 node tree[1000000];
    13
    14 struct man
    15 {
    16 int pos;
    17 int val;
    18 };
    19
    20 man num[200001];
    21 int n;
    22 int ans[200001];
    23
    24 void build(int i,int l,int r)
    25 {
    26 tree[i].l=l;
    27 tree[i].r=r;
    28 tree[i].left=r-l+1;
    29 if(l==r)
    30 return;
    31 int mid=(l+r)/2;
    32 build(2*i,l,mid);
    33 build(2*i+1,mid+1,r);
    34 }
    35
    36 void updata(int i,int w,int val)
    37 {
    38 if(tree[i].left>=w)
    39 {
    40 if(tree[i].l==tree[i].r)
    41 {
    42 tree[i].left--;
    43 ans[tree[i].l]=val;
    44 return;
    45 }
    46 if(tree[i].l<tree[i].r)
    47 {
    48 if(tree[2*i].left>=w)
    49 updata(2*i,w,val);
    50 else if(tree[2*i+1].left>=w-tree[2*i].left)
    51 updata(2*i+1,w-tree[2*i].left,val);
    52 tree[i].left=tree[2*i].left+tree[2*i+1].left;
    53 }
    54 }
    55 }
    56
    57 int main()
    58 {
    59 int i,pos;
    60 freopen("in.txt","r",stdin);
    61 while(scanf("%d",&n)!=EOF)
    62 {
    63 build(1,1,n);
    64 for(i=0;i<n;i++)
    65 {
    66 scanf("%d%d",&num[i].pos,&num[i].val);
    67 }
    68 for(i=n-1;i>=0;i--)
    69 {
    70 pos=i-num[i].pos+1; //i-num[i].pos表示要插队的数目,插x个队,最终的位置便是x+1,所以+1
    71 updata(1,pos,num[i].val);
    72 }
    73 int flag=0;
    74 for(i=n;i>=1;i--)
    75 {
    76 if(flag)
    77 printf("");
    78 printf("%d",ans[i]);
    79 flag=1;
    80 }
    81 printf("\n");
    82 }
    83 return 0;
    84 }



  • 相关阅读:
    php详解和优化
    接口
    抽象类
    对象转型
    面向对象2
    Super关键字
    Object类介绍
    有效处理java异常的三个原则
    this关键字
    equals方法
  • 原文地址:https://www.cnblogs.com/ka200812/p/2248088.html
Copyright © 2020-2023  润新知