标签:south 大学生 space sizeof play 思路 mis lin splay
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 919 Accepted Submission(s): 290
有N个村庄 [ 横纵坐标为 x , y ( x , y >= 1 && x , y <=1e9 ) ] , 每到一个村庄 我们可以选择向上向右或者向右上方走,每个村庄有一个贡献值,只有当我是从左下方的村庄来的才可以得到当前村庄的贡献值。
离散化 +排序+树状数组维护区间最大值
坐标 x, y 的范围太大,而节点范围还可以,所以不妨离散化一波(听说实际测试数据范围没有到1e9,出题人就料定我们没有这个胆)。
一开始用传统 dp ,状态转移很好想,但很明显会超时,交了两波TLE果断自闭。
这道题是正确打开方式是线段树或者树状数组维护区间最大值,而这里的区间是 y 的区间。然后通过前一行的最优值去转移得到当前行的最优值,不过排序顺序需要注意,因为只有左下方的可以转移过来所以当 x 相同时,优先处理 y 大的。
AC code:
1 #include <bits/stdc++.h> 2 #define ll long long int 3 #define INF 0x3f3f3f3f 4 #define mod 1000000007 5 using namespace std; 6 7 const int MAXN = 1e5+10; 8 9 struct date{ 10 int x, y, v; 11 }node[MAXN]; 12 13 int d[MAXN], dp[MAXN]; 14 int t[MAXN<<1]; 15 int N; 16 17 bool cmp1(struct date a, struct date b) 18 { 19 if(a.x == b.x) return a.y > b.y; 20 return a.x < b.x; 21 } 22 int lowbit(int x) 23 { 24 return x&(-x); 25 } 26 void add(int st, int val) 27 { 28 for(int i = st; i <= MAXN; i+=lowbit(i)) 29 t[i] = max(t[i], val); 30 } 31 int query(int st) 32 { 33 int res = 0; 34 for(int i = st; i > 0; i-=lowbit(i)) 35 res = max(res, t[i]); 36 return res; 37 } 38 39 int main() 40 { 41 int T; 42 scanf("%d", &T); 43 while(T--){ 44 scanf("%d", &N); 45 memset(t, 0, sizeof(t)); 46 for(int i = 1; i <= N; i++){ 47 scanf("%d%d%d", &node[i].x, &node[i].y, &node[i].v); 48 d[i] = node[i].y; 49 } 50 sort(d+1, d+N+1); 51 int last = unique(d+1, d+1+N)-1-d; 52 for(int i = 1; i <= N; i++) 53 node[i].y = lower_bound(d+1, d+1+last, node[i].y)-d; 54 sort(node+1, node+1+N, cmp1); 55 for(int i = 1; i <= N; i++) 56 { 57 int res = query(node[i].y-1) + node[i].v; 58 add(node[i].y, res); 59 } 60 printf("%d\n", query(MAXN-1)); 61 } 62 return 0; 63 }
2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】
标签:south 大学生 space sizeof play 思路 mis lin splay
原文地址:https://www.cnblogs.com/ymzjj/p/9537617.html