1. 程式人生 > >HDU6447 YJJ's Salesman-2018CCPC網絡賽-線段樹求區間最值+離散化+dp

HDU6447 YJJ's Salesman-2018CCPC網絡賽-線段樹求區間最值+離散化+dp

fine 滾動 tps 記得 size names sum 離散 圖片

目錄

  • 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從大到小,每次更行一行。

?按01背包的更新順序,滾動數組優化為一維。
?細節見代碼。

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