HDU6447 YJJ's Salesman-2018CCPC網絡賽-線段樹求區間最值+離散化+dp
阿新 • • 發佈:2018-08-26
fine 滾動 tps 記得 size names sum 離散 圖片
?按01背包的更新順序,滾動數組優化為一維。
?細節見代碼。
目錄
- Catalog
- Solution:
(有任何問題歡迎留言或私聊 && 歡迎交流討論哦
Catalog
Problem:Portal傳送門
?原題目描述在最下面。
?1e5個點,問從(0,0)走到(1e9,1e9)的最大收益。
?當你從(u-1,v-1)走到(u,v)時,你可以獲得點(u,v)的權值。
Solution:
?十分詳細了。
?直接線段樹區間最值。當然也可以樹狀數組,不能st表。
?\(dp[i] = max(query\_max(0,dp[i]-1,1)+val[i] ,dp[i])\)
?\(update(i, dp[i],1)\)
?記得離散化再排序,先x從小到大,再y從大到小,每次更行一行。
?細節見代碼。
AC_Code:
#include<bits/stdc++.h> #define lson rt<<1 #define rson rt<<1|1 #define mme(a,b) memset((a),(b),sizeof((a))) using namespace std; typedef unsigned long long LL; const int N = 2e5 + 7; const int M = 1e5 + 7; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; int ar[N],br[N];//離散化 int dp[N]; struct lh{//儲存1e5個點 int x,y,v; }op[N]; bool cmp(lh &a,lh &b){ if(a.x!=b.x)return a.x<b.x; return a.y>b.y; } int n; /**********線段樹區間最值**********/ struct lp{ int l, r, sum; }cw[N<<2]; void push_up(int rt){ cw[rt].sum = max(cw[lson].sum, cw[rson].sum); } void build(int l,int r,int rt){ cw[rt].l = l;cw[rt].r = r;cw[rt].sum = 0; if(l==r){ return; } int mid = (l+r)/2; build(l,mid,lson);build(mid+1,r,rson); push_up(rt); } void update(int p,int c,int rt){ int l = cw[rt].l, r = cw[rt].r,mid = (l+r)/2; if(l==r){ cw[rt].sum = c; return; } if(p<=mid)update(p,c,lson); else update(p,c,rson); push_up(rt); } int query(int L,int R,int rt){ int l = cw[rt].l, r = cw[rt].r,mid = (l+r)/2; if(L<=l&&r<=R){ return cw[rt].sum; } if(L>mid)return query(L,R,rson); else if(R<=mid)return query(L,R,lson); return max(query(L,mid,lson),query(mid+1,R,rson)); } /****************/ int main(){ int tim; scanf("%d", &tim); while(tim--){ scanf("%d", &n); for(int i = 0; i < n; ++i){ scanf("%d%d%d",&op[i].x,&op[i].y,&op[i].v); ar[i] = op[i].x;br[i]=op[i].y; } int p = n + 1; ar[n] = 0;br[n] = 0; sort(ar,ar+p); sort(br,br+p); int a = unique(ar,ar+p)-ar; int b = unique(br,br+p)-br; for(int i = 0; i < n; ++i){ op[i].x=lower_bound(ar,ar+a,op[i].x)-ar; op[i].y=lower_bound(br,br+b,op[i].y)-br; } //以上離散化 sort(op,op+n,cmp); build(0, b, 1); mme(dp, 0); for(int i = 0; i < n; ++i){ int flag = op[i].x, j; for(j = i; j < n; ++j){ if(op[j].x != flag){ break; } int tmp = query(0, op[j].y-1, 1) + op[j].v; if(tmp > dp[op[j].y]){ dp[op[j].y] = tmp; update(op[j].y, dp[op[j].y], 1); } } i = j - 1; } int ans = 0; for(int i = 0; i <= b; ++i){ ans = max(ans, dp[i]); } printf("%d\n", ans); } return 0; }
Problem Description:
HDU6447 YJJ's Salesman-2018CCPC網絡賽-線段樹求區間最值+離散化+dp