• bzoj4380: [POI2015]Myjnie


    Description

    有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]。
    有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i],那么这个人就不洗车了。
    请给每家店指定一个价格,使得所有人花的钱的总和最大。

    Input

    第一行包含两个正整数n,m(1<=n<=50,1<=m<=4000)。
    接下来m行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<=b[i]<=n,1<=c[i]<=500000)

    Output

    第一行输出一个正整数,即消费总额的最大值。
    第二行输出n个正整数,依次表示每家洗车店的价格p[i],要求1<=p[i]<=500000。
    若有多组最优解,输出任意一组。

    用dp确定笛卡尔树的形态,f[l][r][v]表示区间[l,r]的最小值为v时,区间内的最大收益,转移时枚举最小值的位置用子区间更新,时间复杂度$O(n^3m)$。
    #include<bits/stdc++.h>
    int n,m,ls[4111],rs[4111],v0[4111],v1[4111],vs[4111],v2[4111];
    int f[53][53][4011],g[53][53][4011],fw[53][53][4011];
    inline bool in(int a,int l,int r){return l<=a&&a<=r;}
    inline bool maxs(int&a,int b){return a<b?a=b,1:0;}
    inline int max(int a,int b){return a>b?a:b;}
    void pr(int l,int r,int h){
        if(l>r)return;
        int h1=h;
        for(;f[l][r][h1]!=g[l][r][h];--h1);
        int p=fw[l][r][h1];
        if(!p)p=l;
        pr(l,p-1,h1);
        printf("%d ",vs[h1]);
        pr(p+1,r,h1);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)scanf("%d%d%d",ls+i,rs+i,v0+i),vs[i]=v0[i];
        std::sort(vs+1,vs+m+1,std::greater<int>());
        for(int i=1;i<=m;++i)v1[i]=std::lower_bound(vs+1,vs+m+1,v0[i],std::greater<int>())-vs;
        for(int l=n;l;--l){
            for(int r=l;r<=n;++r){
                int*F=f[l][r],*G=g[l][r],*FW=fw[l][r];
                for(int p=l;p<=r;++p){
                    for(int h=1;h<=m;++h)v2[h]=0;
                    for(int h=1;h<=m;++h)if(in(ls[h],l,p)&&in(rs[h],p,r))++v2[v1[h]];
                    for(int h=2;h<=m;++h)v2[h]+=v2[h-1];
                    int*GL=g[l][p-1],*GR=g[p+1][r];
                    for(int h=1;h<=m;++h)if(maxs(F[h],GL[h]+GR[h]+v2[h]*vs[h]))FW[h]=p;
                }
                for(int h=1;h<=m;++h)G[h]=max(G[h-1],F[h]);
            }
        }
        printf("%d
    ",g[1][n][m]);
        pr(1,n,m);
        return 0;
    }
  • 相关阅读:
    JS框架_(Bootstrap.js)实现简单的轮播图
    Unity3D_(网格导航)简单物体自动寻路
    Android_(菜单)选项菜单
    Android_(传感器)获取手机中的传感器
    Java基础__Java中常用数学类Math那些事
    Java基础__Java中异常处理那些事
    Android_(控件)动态添加或删除Spinner下拉菜单
    Android_(消息提示)多种使用Toast的消息提示
    Java基础__随机生成1~15之间不重复的数字
    Android_(自动化)获取手机存储卡的容量
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7526765.html
Copyright © 2020-2023  润新知