Codeforces Round #401 (Div. 2) E 离散化 + 树状数组/线段树

来源:互联网 发布:如何评价海贼王 知乎 编辑:程序博客网 时间:2024/05/17 03:05

题目链接

思路:
感觉像是背包问题的变形…..
很直接的DP策略:
首先先对物体进行排序,外半径大的先处理。(考虑无后效性,因为对于外半径最大的物品是不能堆在其他物品上面的。)
设dp[i]是处理到第i个物体时可以达到的最高高度。

dp[i] = max{dp[j]} + h[i]
其中 1 <= j < i && b[i] > a[j]。

故需要动态维护区间最值,可用线段树或树状数组的写法
代码:

数组数组:

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const ll INF = 1e16 + 7;const int A = 1e6 + 10;class P{public:    int n;    ll tree[A<<1];    void init(int _n){        n = _n;        for(int i=1 ;i<=n ;i++){            tree[i] = -INF;        }    }    ll query(int pos){        ll res = -INF;        for(int i=pos ;i>0 ;i-=(i&(-i))) res = max(res,tree[i]);        return res;    }    void update(int pos,ll val){        for(int i=pos ;i<=n ;i+=(i&(-i)))   tree[i] = max(tree[i],val);    }}bit;class Node{public:    int a,b,h;    bool operator <(const Node& rhs) const{        if(b == rhs.b) return a > rhs.a;        return b > rhs.b;    }}x[A];int y[A<<1];int main(){    int n;    scanf("%d",&n);    int tot = 0;    for(int i=1 ;i<=n ;i++){        scanf("%d%d%d",&x[i].a,&x[i].b,&x[i].h);        y[tot++] = x[i].a;        y[tot++] = x[i].b;    }    sort(y,y+tot);    tot = unique(y,y+tot) - y;    for(int i=1 ;i<=n ;i++){        x[i].a = lower_bound(y,y+tot,x[i].a) - y + 1;        x[i].b = lower_bound(y,y+tot,x[i].b) - y + 1;    }    sort(x+1,x+n+1);    bit.init(2*n);    ll ans = -INF;    for(int i=1 ;i<=n ;i++){        ll now = max(0LL,bit.query(x[i].b-1)) + x[i].h;        ans = max(ans,now);        bit.update(x[i].a,now);    }    printf("%I64d\n",ans);    return 0;}

线段树:

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const ll INF = 1e16 + 7;const int A = 1e6 + 10;class P{public:    int l,r;    ll Max;}tree[A<<2];class Node{public:    int a,b,h;    bool operator <(const Node& rhs) const{        if(b == rhs.b) return a > rhs.a;        return b > rhs.b;    }}x[A];int y[A<<1];void push_up(int id){    tree[id].Max = max(tree[id<<1].Max,tree[id<<1|1].Max);}void build_Tree(int id,int l,int r){    tree[id].l = l,tree[id].r = r;    tree[id].Max = 0;    if(l == r) return;    int mid = (l+r)>>1;    build_Tree(id<<1,l,mid);    build_Tree(id<<1|1,mid+1,r);}ll query(int id,int st,int ed){    int l = tree[id].l,r = tree[id].r;    if(st <= l && r <= ed) return tree[id].Max;    int mid = (l+r)>>1;    ll res = 0;    if(st <= mid) res = max(res,query(id<<1,st,ed));    if(ed >  mid) res = max(res,query(id<<1|1,st,ed));    return res;}void update(int id,int pos,ll val){    int l = tree[id].l,r = tree[id].r;    if(l == r){        tree[id].Max = max(tree[id].Max,val);        return;    }    int mid = (l+r)>>1;    if(pos <= mid) update(id<<1,pos,val);    else           update(id<<1|1,pos,val);    push_up(id);}int main(){    int n;    scanf("%d",&n);    int tot = 0;    for(int i=1 ;i<=n ;i++){        scanf("%d%d%d",&x[i].a,&x[i].b,&x[i].h);        y[tot++] = x[i].a;        y[tot++] = x[i].b;    }    sort(y,y+tot);    tot = unique(y,y+tot) - y;    int m = 0;    for(int i=1 ;i<=n ;i++){        x[i].a = lower_bound(y,y+tot,x[i].a) - y + 1;        x[i].b = lower_bound(y,y+tot,x[i].b) - y + 1;        m = max(m,x[i].a),m = max(m,x[i].b);    }    sort(x+1,x+n+1);    build_Tree(1,1,m);    ll ans = -INF;    for(int i=1 ;i<=n ;i++){        ll now = query(1,1,x[i].b-1) + x[i].h;        ans = max(ans,now);        update(1,x[i].a,now);    }    printf("%I64d\n",ans);    return 0;}
0 0
原创粉丝点击