zoukankan      html  css  js  c++  java
  • HDU 4719Oh My Holy FFF 线段树+DP

    /*
    **  日期: 2013-9-12
    **  题目大意:有n个数,划分为多个部分,假设M份,每份不能多于L个。每个数有一个h[i],
    **  每份最右边的那个数要大于前一份最右边的那个数。设每份最右边的数为b[i],
    **  求最大的sum{b[i]² - b[i - 1]},1≤i≤M,其中b[0] = 0。
    **  思路:朴素DP为,dp[i]表示以i为结尾的最大划分。那么dp[i] = max{dp[j] - h[j] + h[i]²},
    **  1≤i-j≤L,h[j]<h[i]。这种会超时,采取线段树优化。因为有两个限制,考虑到若h[j]≥h[i],
    **  那么求i的时候一定不会用到j,那么先按h排序再DP(h相同的,i大的排前面)。
    **  __int64 没改完,导致wa了无数次
    */
    
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define lson rt<<1,left,m
    #define rson rt<<1|1,m+1,right
    #define mid  (left+right)>>1
    using namespace std;
    
    typedef __int64 LL ;
    const int maxn = 100005;
    LL maxt[maxn<<2];
    int L,n;
    struct node{
        int pos;LL h;
        node(int id = 0,LL hight = 0):pos(id),h(hight){}
        bool operator < (node a)const{
            if( h == a.h)return pos > a.pos;
            return h < a.h;
        }
    }arr[maxn];
    void update(int rt,int left,int right,int place,LL val){
        if( left == right){
            maxt[rt] = val;
            return ;
        }
        int m = mid;
        if( place <= m)update(lson,place,val);
        else update(rson,place,val);
        maxt[rt] = max(maxt[rt<<1],maxt[rt<<1|1]);
    }
    LL query(int rt,int left,int right,int l,int r){
        if( left >= l && right <= r){
            return maxt[rt];
        }
        int m = mid;
        LL res = -1;
        if( l <= m)res = max(res,query(lson,l,r));
        if( r > m )res = max(res,query(rson,l,r));
        return res;
    }
    LL solve(){
        sort(arr,arr+n);
        LL res = -1;
        memset(maxt,-1,sizeof(maxt));
        update(1,0,n,0,0);
        for(int i = 0; i < n; i++){
            LL tmp = query(1,0,n,max(arr[i].pos-L,0),arr[i].pos - 1);
            if( tmp == -1 ){
                if( arr[i].pos == n)return -1;
                continue;
            }
            res = tmp + (LL)arr[i].h*arr[i].h;
            if( arr[i].pos == n)return res;
            update(1,0,n,arr[i].pos,res - arr[i].h);
        }
        return res;
    }
    int main(){
        int t,cas = 1;LL h;
        scanf("%d",&t);
        while( t-- ){
            scanf("%d%d",&n,&L);
            for(int i = 0; i < n; i++){
                scanf("%I64d",&h);
                arr[i] = node(i+1,h);
            }
            LL ans = solve();
            printf("Case #%d: ",cas++);
            if( ans == -1)puts("No solution");
            else printf("%I64d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    安装VS 2015完成后,VS2012 打开报错
    ASP.NET MVC 项目中 一般处理程序ashx 获取Session
    windows平台 查看 dll 程序集 PublicKeyToken
    MySQL 表与字段编码格式报错
    Linux系统下安装MongoDB 指南
    ASP.NET 访问路径 错误提示 HTTP 错误 404.8 原来路径中包含bin目录被拒绝
    ASP.NET 大文件上传
    将类型(int,string,…)转换为 T 类型
    直接插入排序
    MySQL 优化之索引合并(index_merge)
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3317012.html
Copyright © 2011-2022 走看看