• 机房测试9:gift(单调队列优化dp)


    题目:

    数据范围:m<=100   n<=16000

    分析:

    定义dp[i][j]为第i个人负责前j个单位的最大贡献。

    转移:dp[i][j]=max(  dp[i][j],dp[i][k]+(j-(k+1)+1)*w[i]  )

    化简得:dp[i][k]-k*w[i]+j*w[i]

    前半部分与k有关,维护一个单调队列,每一次满足条件后就去更新dp[i][j]

    单调队列的比较方式是上述式子,而里面存的值是位置

    每个人能解决的是一段区间,且必须用起始位置p点,所以先将区间排序(按起点从小到大)

    每次枚举一个人,再枚举j:1~n,将1~n分为三段:

    1. j小于i的起始位置:也就是无法用i,但可以将这一部分的dp值入队(本来是要枚举k的,这里相当于是在枚举k,入队准备更新j)

    2. j在起始位置与其向右最远能覆盖的距离之间:可以用单调队列里面的值来更新j。

    3. j超过了其向右的最远覆盖距离:只能继承前面的状态:dp[i-1][j],dp[i][j-1]

    注意:

    1.每枚举一个点i,就应该把单调队列清空,并把合法的状态先压入队列。

    2.在枚举j的时候,记得把超出范围的点排除

    #include<bits/stdc++.h>
    using namespace std;
    #define M 105
    #define N 160005
    #define ri register int
    struct node{ int l,p,s; }a[M];
    int dp[M][N],q[N];
    bool cmp(const node &a,const node &b)
    {
        return a.s<b.s;
    }
    int main()
    {
        freopen("gift.in", "r", stdin);
        freopen("gift.out", "w", stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        for(ri i=1;i<=m;++i) scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
        sort(a+1,a+1+m,cmp);
        int ans=0,h,t;
        for(ri i=1;i<=m;++i){
            h=1,t=0;
            q[++t]=max(0,a[i].s-a[i].l);//与0取max是因为0可以入队,也就是说在后面更新其他值的时候 可以由一个也不选更新过来 
            for(ri j=1;j<=n;++j){
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                if(j >= a[i].s+a[i].l) continue;//不break是为了更新前一行的状态继承 
                while( h<=t && a[i].l+q[h]<j ) h++;//将无法到达的排除 
                if(j<a[i].s){//i,j合法 则j一定要在i起始位置之前 这里的j相当于式子里面的k 是可以去更新后续j位置的  
                    int tmp=dp[i-1][j]-a[i].p*j;//式子 
                    while( h<=t && tmp>=dp[i-1][q[t]]-a[i].p*q[t] ) t--;//单调递减的序列 
                    q[++t]=j;
                    continue;//这里只是在将k入队 方便更新后面的j 还没达到这个范围 j不能被更新 
                }
                //达到j可以被更新的范围:j>=a[i].s 
                dp[i][j]=max(dp[i][j],dp[i-1][q[h]]+(j-q[h])*a[i].p);//q[h]=k q记录的是位置 通过dp[i][k]-k*w比较 
            }
        }
        printf("%d
    ",dp[m][n]);
    }
    /*
    8 4
    3 2 2
    3 2 3
    3 3 5
    1 1 7
    */
    View Code
  • 相关阅读:
    python 读写XLS
    python去噪算法
    编译freetype 的dll
    python生成测试图片
    python 将pdf分页后插入至word中
    ie height
    Formview单文档或对话框项目接受不到按键消息的解决办法
    SQL SERVER配置[转]
    PyQt5 布局
    PyQt5 各种菜单实现
  • 原文地址:https://www.cnblogs.com/mowanying/p/11640315.html
Copyright © 2020-2023  润新知