HDU 3607 线段树+DP

来源:互联网 发布:mac下载的系统在哪 编辑:程序博客网 时间:2024/06/06 10:41

这题最裸的方法因该是O(n2)的。dp[i]=max(dp[j])+gi(1<=j<i且hi>hj) 其中dp[i]代表的是前i下能拿的最多的钱。 但这个数据范围有点大,是10W 之多。 在hi > hj这个限制下,我们可以联想到,不就是找比hi小的高度中能获得的最多的钱的那个状态么,再由数据范围,容易联想到用线段树优化这个过程。那么就先把所有的高度都离散化,然后每次先进行查询,将比hi小的高度中钱最多的状态找出,更新当前状态,然后再插入树中。


/*ID: CUGB-wwjPROG:LANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define INF 1111111111#define MAXN 111111#define MAXM 444444#define PI acos(-1.0)#define L(X) X<<1#define R(X) X<<1|1using namespace std;struct node{    int left, right, mid;    int mx;}tree[4 * MAXN];int dp[MAXN];int h[MAXN], x[MAXN];void make_tree(int s, int e, int C){    tree[C].left = s;    tree[C].right = e;    tree[C].mid = (s + e) >> 1;    tree[C].mx = 0;    if(s == e) return;    make_tree(s, tree[C].mid, L(C));    make_tree(tree[C].mid + 1, e, R(C));}void up(int C){    tree[C].mx = max(tree[L(C)].mx, tree[R(C)].mx);}void update(int p, int v, int C){    if(tree[C].left == tree[C].right)    {        tree[C].mx = max(tree[C].mx, v);        return;    }    if(tree[C].mid >= p) update(p, v, L(C));    else update(p, v, R(C));    up(C);}int query(int s, int e, int C){    if(tree[C].left >= s && tree[C].right <= e) return tree[C].mx;    int ret = 0;    if(tree[C].mid >= s) ret = max(ret, query(s, e, L(C)));    if(tree[C].mid < e)  ret = max(ret, query(s, e, R(C)));    return ret;}int cnt;int bin(int v){    int low = 1;    int high = cnt;    while(low <= high)    {        int mid = (low + high) >> 1;        if(x[mid] == v) return mid;        if(x[mid] > v) high = mid - 1;        else low = mid + 1;    }    return -1;}int main(){    int n;    while(scanf("%d", &n) != EOF)    {        for(int i = 1; i <= n; i++)        {            scanf("%d%d", &h[i], &dp[i]);            x[i] = h[i];        }        sort(x + 1, x + n + 1);        cnt = unique(x + 1, x + n + 1) - x - 1;        make_tree(1, cnt, 1);        int ans = 0;        for(int i = 1; i <= n; i++)        {            int pos = bin(h[i]);            int val;            if(pos == 1) val = 0;            else val = query(1, pos - 1, 1);            dp[i] += val;            ans = max(dp[i], ans);            update(pos, dp[i], 1);        }        printf("%d\n", ans);    }    return 0;}


原创粉丝点击