计蒜客 17319 The Heaviest Non-decreasing Subsequence Problem
2017-09-24 20:22
405 查看
Problem
nanti.jisuanke.com/t/17319Meaning
给一个整数序列 s,每个数都有个权值,权值的计算方法是:s[i] < 0:s[i] 的权值为 0
s[i] >= 10000:s[i] 的权值为 5,且 s[i] 数值改为
s[i] - 10000
其它:s[i] 权值为 1
现要从序列中,找一个非降的子序列,使得该子序列的权值和最大,求这个最大的权值。
Analysis
容易发现,负数是没有用的,直接忽略。一种思路是拆点:
如果权值都是 1 的话,题目就转换为求最长非降序子序列的长度。
那么,对于权值为 5 的点,把它拆成 5 个权值为 1、数值相同的点,就变成只有权值都是 1 点,就转化为求最长非降序子序列的长度。
另一种思路,不拆点:
定义:
dp[i]:以 s[i] 结尾的子序列能取得的最大权值和
转移:
dp[i] = max { dp[j] + w[i] | j < i,s[j] <= s[i] }
问题在于如何快速找到这个
max { dp[j] }。
可以开一棵权值线段树,记录以每一个 s[j](j < i)结尾的子序列最大的权值和。对于 s[i],查询 [ 0,s[i] ] 这个区间的最大值,这个最大值就是要找的
max{dp[j]},用
max{dp[j]} + w[i]更新树上 s[i] 结尾的那条记录(即 dp[s[i]]),然后更新答案。
由于题目没给数值的范围,所以先离散化一下。
Code
拆点
#include <cstdio> using namespace std; const int N = 200000, BUF = 50, CAP = 10000; char buf[BUF+7]; int getint() { int res = 0, sgn = 1; char *p = buf; if(*p == '-') { sgn = -1; ++p; } while(*p) res = res * 10 + *p++ - '0'; return sgn * res; } int a[N+1]; int bs(int r, int x) { for(int l = -1, m; l + 1 < r; ) { m = l + r >> 1; if(a[m] <= x) l = m; else r = m; } return r; } int main() { int r = 0; for(int s, n; ~scanf("%s", buf); ) { s = getint(); // 负数忽略 if(s < 0) continue; n = 1; if(s >= CAP) { s -= CAP; n = 5; } // 做 n 次 LIS for(int p; n--; ) { p = bs(r, s); if(p == r) ++r; a[p] = s; } } printf("%d\n", r); return 0; }
不拆点
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 200000, CAP = 10000, BUF = 50; int readint(int &res) { static char buf[BUF+7]; res = 0; if(scanf("%s", buf) == EOF) return EOF; int sgn = 1; char *p = buf; if(*p == '-') { sgn = -1; ++p; } while(*p) res = res * 10 + *p++ - '0'; res *= sgn; return 1; } int tree[N+7<<2]; inline void pushup(int x) { tree[x] = max(tree[x<<1], tree[x<<1|1]); } void update(int p, int v, int l, int r, int rt) { if(l == r) { tree[rt] = v; return; } int m = l + r >> 1; if(m < p) update(p, v, m+1, r, rt<<1|1); else update(p, v, l, m, rt<<1); pushup(rt); } int query(int ql, int qr, int l, int r, int rt) { if(ql <= l && r <= qr) return tree[rt]; int m = l + r >> 1, res = 0; if(ql <= m) res = max(res, query(ql, qr, l, m, rt<<1)); if(qr > m) res = max(res, query(ql, qr, m+1, r, rt<<1|1)); return res; } int s , w , dsc ; int main() { freopen("in.txt", "r", stdin); int n = 0; while(~readint(s )) if(s >= 0) // 负数忽略 { if(s >= CAP) { s -= CAP; w = 5; } else w = 1; dsc = s ; ++n; } // 离散化 sort(dsc, dsc + n); int m = unique(dsc, dsc + n) - dsc; memset(tree, 0, sizeof tree); int ans = 0; for(int i = 0, v, pre; i < n; ++i) { v = lower_bound(dsc, dsc + m, s[i]) - dsc; // 查询 dp[j] pre = query(0, v, 0, m, 1); // 更新 dp[s[i]] update(v, pre + w[i], 0, m, 1); // 更新答案 ans = max(ans, tree[1]); // query(0, m, 0, m, 1); } printf("%d\n", ans); return 0; }
相关文章推荐
- 计蒜客 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 The Heaviest Non-decreasing Subsequence Problem
- 计蒜客 2017icpc南宁赛区 The Heaviest Non-decreasing Subsequence Problem 最长不递减子序列
- 计蒜客 The Heaviest Non-decreasing Subsequence Problem dp LIS变形 || 线段树+dp
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 The Heaviest Non-decreasing Subsequence Problem
- 最长不减子序列变形 The Heaviest Non-decreasing Subsequence Problem 南宁网络赛
- 计蒜客 The Heaviest Non-decreasing Subsequence Problem(最大权值和非递减子序列)
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 L.The Heaviest Non-decreasing Subsequence Problem
- The Heaviest Non-decreasing Subsequence Problem(2017南宁网络赛)
- The Heaviest Non-decreasing Subsequence Problem ACM-ICPC南宁wa
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 The Heaviest Non-decreasing Subsequence Problem
- The Heaviest Non-decreasing Subsequence Problem
- 2017ICPC南宁赛区网络赛 The Heaviest Non-decreasing Subsequence Problem (最长不下降子序列)
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛-L. The Heaviest Non-decreasing Subsequence Problem
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 The Heaviest Non-decreasing Subsequence Problem 最长不下降序列
- The Heaviest Non-decreasing Subsequence Problem 最长非递减子序列 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛
- 2017 icpc 南宁赛区 L.The Heaviest Non-decreasing Subsequence Problem(LIS)
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 L. The Heaviest Non-decreasing Subsequence Problem(最长不下降子序列变形)
- ???The Heaviest Non-decreasing Subsequence Problem
- The Heaviest Non-decreasing Subsequence Problem
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 L. The Heaviest Non-decreasing Subsequence Problem