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 }