Description
There are n irony ring in a factory. The i-th ring has inner radius ai, outer radius bi and height hi. The goal is to select some subset of irony ring to create as high town as possible . The subset of irony ring following condition are satisifed:
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;the above ring’s outer radius should longer than the below ring’s
inner radius. That means one can place ring j on the ring i only if
bj>ai.The total height of ring used should be maximum possible.
Input
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1922
Output
Print one integer – the maximum height of the tower that can be obtained.
Sample Input
3
1 5 1
2 6 2
3 7 3
4
1 2 1
1 3 3
4 6 2
5 7 1
Sample Output
6
4
题意:
有n个铁环,每个铁环有内半径ai,外半径bi,还有高度hi,然后要用这些铁环来建一座建筑,放在上面的铁环必须满足:1)上面的外半径bi比下面的外半径bj要小;2)上面的外半径bj要比下面的内半径ai要大,3)要求叠起来最高
解法:
解法有两种,一种是使用线段树,将内径和外径看做区间边界【l,r】 每个戒指算作一个更新,在l,r之间加上高度h,不断维护最大值。 最后输出整个区间的最大值即可。应为l,r的数据范围是1e9 而线段树的合理区间是1e7,所以要离散化。
离散化的方法是: 将所有的l,r排序 ,然后区间更新
线段树的写法是 首先,你把外径从大到小排序
如果外径相等,把内径从大到小排序 之后的顺序,外径就是非递增的 那么对于当前我们枚举第i个ring,外径是S[i].b,内径是S[i].a
这个rin只能放在内径小与S[i].b的上面 我们线段树,第i个叶子维护一个叠起来的东西中,最上面那个ring的内径为i,此时的高度
所以我们只要在线段树中查询[1,S[i].b-1]中的最大值,就是我当前可以放之后的最高高度了(基神强无敌)
线段树写法的的复杂度是nlongn 常数很大
第二种是贪心求解
就是将这些铁环排序,外半径越大的越前面,一样大的话内半径越大的越前面,然后用一个栈来维护当前被叠起来的铁环,还有一个ans值来记录当前的最大的高度,然后每次放一个铁环上来的时候判断当前的条件是否满足,不满足就拿掉当前的铁环,知道满足,然后从新判断当前高度是否比原来的的最大高度大,大的话就更新 复杂度同样为nlongn 常数小
线段树版代码
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <climits>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
const int MX = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int mod = 1e9 + 7;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,bsz,1
int n;
struct Data {
int a, b, h;
bool operator<(const Data &P)const {
if(b == P.b) return a > P.a;
return b > P.b;
}
} A[MX];
int SB[2 * MX], bsz;
ll MAX[MX << 2];
void push_up(int rt) {
MAX[rt] = max(MAX[rt << 1], MAX[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
MAX[rt]=0;
if(l == r) {
return;
}
int m = (l + r) >> 1;
build(lson); build(rson);
}
ll query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return MAX[rt];
}
int m = (l + r) >> 1; ll ret = 0;
if(L <= m) ret = max(ret, query(L, R, lson));
if(R > m) ret = max(ret, query(L, R, rson));
return ret;
}
void update(int p, ll x, int l, int r, int rt) {// 此种写法 每次只更新了一个点 复杂度logn
if(l == r) {
MAX[rt] = max(MAX[rt], x);
return;
}
int m = (l + r) >> 1;
if(p <= m) update(p, x, lson);
else update(p, x, rson);
push_up(rt);
}
int id(int x) {
return lower_bound(SB + 1, SB + 1 + bsz, x) - SB;
}
int main() {
//FIN;
while(~scanf("%d", &n)) {
bsz = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%d%d", &A[i].a, &A[i].b, &A[i].h);
SB[++bsz] = A[i].a;
SB[++bsz] = A[i].b;
}
sort(A + 1, A + 1 + n);
sort(SB + 1, SB + 1 + bsz);
bsz = unique(SB + 1, SB + 1 + bsz) - SB - 1;// 离散化去重
for(int i = 1; i <= n; i++) {
A[i].a = id(A[i].a);
A[i].b = id(A[i].b);
}
build(root);
for(int i = 1; i <= n; i++) {
ll now = 1 <= A[i].b - 1 ? query(1, A[i].b - 1, root) : 0;
update(A[i].a, now + A[i].h, root);
}
ll ans = query(1, bsz, root);
printf("%lld\n", ans);
}
return 0;
}
贪心代码
#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<stack>
#define fuck(x) cout<<"["<<x<<"]"<<endl
using namespace std;
const int MAX=1e5+10;
class ring
{
public:
long long w,n,h;
ring(long long w,long long n,long long h):w(w),n(n),h(h){}
ring (){}
};
bool cmp(ring a,ring b)
{
if(a.w==b.w)
{
return a.n>b.n;
}
return a.w>b.w;
}
ring rings[MAX];
stack<ring> S;
long long maxhi,nowmaxs;
void my_push(ring ns)
{
while(!S.empty())
{
ring cnt=S.top();
if(cnt.n>=ns.w)
{
S.pop();
nowmaxs-=cnt.h;
}
else break;
}
S.push(ns);
nowmaxs+=ns.h;
maxhi=max(nowmaxs,maxhi);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
// fuck(n);
for(int i=0;i<n;i++)
{
scanf("%lld %lld %lld",&rings[i].n,&rings[i].w,&rings[i].h);
//fuck(rings[i].h);
}
sort(rings,rings+n,cmp);
while(!S.empty())
{
S.pop();
}
//S.push(ring(1e9+5,0,0));
maxhi=nowmaxs=0;
for(int i=0;i<n;i++)
{
my_push(rings[i]);
}
cout<<maxhi<<endl;
}
return 0;
}