zoukankan      html  css  js  c++  java
  • HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp

    (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

    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
    ", ans);
      }
      return 0;
    }
    

    ####Problem Description: ![这里写图片描述](https://img-blog.csdn.net/20180825234959255)
  • 相关阅读:
    老年人微信教程手绘版|微信入门教程1
    微信网页版朋友圈在哪?怎么找不到
    如何用<dl>标签做表格而不用table标签
    600万个!520元的微信红包发了这么多!
    微信红包最高能发520元啦!只限今天!
    微信和WeChat的合并月活跃账户数达到7.62亿了
    excel隔行选中内容如何操作
    各大公司广泛使用的在线学习算法FTRL详解
    在线最优化求解(Online Optimization)之五:FTRL
    在线最优化求解(Online Optimization)之四:RDA
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/9535914.html
Copyright © 2011-2022 走看看