• Codeforces Round #401 E题Hanoi Factory(线段树、离散化)解题报告


    E. Hanoi Factory
    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Of course you have heard the famous task about Hanoi Towers, but did you know that there is a special factory producing the rings for this wonderful game? Once upon a time, the ruler of the ancient Egypt ordered the workers of Hanoi Factory to create as high tower as possible. They were not ready to serve such a strange order so they had to create this new tower using already produced rings.

    There are n rings in factory's stock. The i-th ring has inner radius ai, outer radius bi and height hi. The goal is to select some subset of rings and arrange them such that the following conditions are satisfied:

    • Outer radiuses form a non-increasing sequence, i.e. one can put the j-th ring on the i-th ring only if bj ≤ bi.
    • Rings should not fall one into the the other. That means one can place ring j on the ring i only if bj > ai.
    • The total height of all rings used should be maximum possible.
    Input

    The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of rings in factory's stock.

    The i-th of the next n lines contains three integers aibi and hi (1 ≤ ai, bi, hi ≤ 109, bi > ai) — inner radius, outer radius and the height of the i-th ring respectively.

    Output

    Print one integer — the maximum height of the tower that can be obtained.

    Examples
    input
    3
    1 5 1
    2 6 2
    3 7 3
    output
    6
    input
    4
    1 2 1
    1 3 3
    4 6 2
    5 7 1
    output
    4
    Note

    In the first sample, the optimal solution is to take all the rings and put them on each other in order 3, 2, 1.

    In the second sample, one can put the ring 3 on the ring 4 and get the tower of height 3, or put the ring 1 on the ring 2 and get the tower of height 4.

    解题思路:

    离散化方法:把所有的ai、bi放入一个数组,进行unique操作之后得到不同数值个数,每次用lower_bound 求出对应的新编号,以后的操作都按照这一编号进行。

    先对所有环排序,排序规则为 bi为第一参考,按升序,ai为第二参考,按升序。线段树每个区间(编号区间)表示以该区间内某一编号的环为底形成的最大高度。(这里用到了一个贪心想法:在外半径相同时,把内半径小的放在上面是更优的做法,所以按照此顺序更新线段树)所有都进行完毕之后再对全体区间询问即可(直接输出线段树的根节点即可)

     1 #include <iostream>
     2 #include<bits/stdc++.h>
     3 #include <stack>
     4 #include <queue>
     5 #include <map>
     6 #include <set>
     7 #include <cstdio>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <math.h>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef unsigned long long ull;
    14 int n;
    15 const int MAX=1e5+10;
    16 struct ring
    17 {
    18     int a,b,h;
    19     friend bool operator < (const ring &aa,const ring &bb)
    20     {
    21         if(aa.b==bb.b)
    22             return aa.a<bb.a;
    23         return aa.b<bb.b;
    24     }
    25 }R[MAX];
    26 ll height[10*MAX];//储存以某个k为下标表示的区间中的某个为底 垒成的塔的高度的最大值
    27 ll query(int k,int l,int r,int ql,int qr)//在[l,r]区间中询问 在[ql,qr]中的区间的值
    28 {
    29     if(l==ql&&r==qr)
    30         return height[k];
    31     int mid=(l+r)/2;
    32     if(qr<=mid)
    33         return query(2*k,l,mid,ql,qr);//返回左子区间的询问
    34     else if(ql>mid)
    35         return query(2*k+1,mid+1,r,ql,qr);
    36     else return max(query(2*k,l,mid,ql,mid),query(2*k+1,mid+1,r,mid+1,qr));
    37 }
    38 void update(int k,int l,int r,int lo,ll val)//单点更新
    39 {
    40     if(l==r&&l==lo)//如果找到了这个点
    41     {
    42         height[k]=val;
    43         return ;
    44     }
    45     int mid=(l+r)/2;
    46     if(lo<=mid)
    47         update(2*k,l,mid,lo,val);
    48     else update(2*k+1,mid+1,r,lo,val);
    49     height[k]=max(height[2*k],height[2*k+1]);//更新此区间
    50 }
    51 int discrete[2*MAX];//进行离散化的数组
    52 int cnt;
    53 int num;//离散化后总共的个数
    54 int getpos(int x)
    55 {
    56     return lower_bound(discrete+1,discrete+1+num,x)-discrete;
    57 }
    58 int main()
    59 {
    60     scanf("%d",&n);
    61     int i;
    62     ll maxn;//储存把已有的环组合放在某个环上可能形成的最大高度
    63     for(i=1;i<=n;i++)
    64     {
    65         scanf("%d %d %d",&R[i].a,&R[i].b,&R[i].h);
    66         discrete[++cnt]=R[i].a;discrete[++cnt]=R[i].b;//所有用于比较的a,b都放入此数组进行以后的操作
    67     }
    68     sort(R+1,R+1+n);
    69     sort(discrete+1,discrete+1+cnt);
    70     num=unique(discrete+1,discrete+1+cnt)-(discrete+1);//unique返回值为进行处理后的最后一个位置(其实是下一个),二者之差即为不同元素个数
    71     for(i=1;i<=n;i++)//用这个编号为i的环为底
    72     {
    73         maxn=query(1,1,num,getpos(R[i].a+1),getpos(R[i].b));//在已有的环组合中找可以放在当前环上的最大的高度
    74         update(1,1,num,getpos(R[i].b),maxn+R[i].h);//将这个为底的环数据更新
    75     }
    76     printf("%lld
    ",query(1,1,num,1,num));
    77     return 0;
    78 }
  • 相关阅读:
    SAP系统玩阴的?
    SAP MM 采购信息记录中价格单位转换因子的修改
    SAP MM 特殊库存之T库存初探
    Gnome增加消息提醒extension ( Fedora 28 )
    Arch Linux 更新源(以清华 arch 源为例)
    fedora 28 , firewalld 防火墙控制,firewall-cmd 管理防火墙规则
    apache 访问权限出错,apache selinux 权限问题, (13) Permission Denied
    什么是中间件? (保持更新)
    systemd 和 如何修改和创建一个 systemd service (Understanding and administering systemd)
    进入正在运行的 docker 容器(docker container)
  • 原文地址:https://www.cnblogs.com/quintessence/p/6476492.html
Copyright © 2020-2023  润新知