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