poj1821 单调队列优化

//poj1821
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define INF 0x7fffffff
using namespace std;
struct node
{
    int L,P,S;
} a[222];
bool cmp(node x,node y)
{
    return x.S<y.S;
}
int n,k;
int dp[222][22222];
struct node2
{
    int m,pos;
    node2 (){}
    node2 (int x,int y){m=x;pos=y;}
};
deque<node2> q;
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(int i=1; i<=k; i++)
        {
            scanf("%d%d%d",&a[i].L,&a[i].P,&a[i].S);
        }
        sort(a+1,a+1+k,cmp);
        for(int i=1; i<=k; i++) //dp[i][j]表示前i个人刷前j面墙的最大值
        {
            for(int j=0; j<a[i].S; j++)
                {
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            while(!q.empty()) q.pop_back();
            for(int kk=max(0,(a[i].S-a[i].L)); kk<=(a[i].S-1); kk++)
            {
                int tmp=dp[i-1][kk]-kk*a[i].P;
                while(!q.empty()&&q.back().m<=tmp) q.pop_back();
                node2 b;
                b.m=tmp;b.pos=kk;
                    q.push_back(b);
            }
            for(int j=a[i].S; j<=min(a[i].S+a[i].L-1,n); j++)
            {
                while(!q.empty()&&q.front().pos<j-a[i].L) q.pop_front();
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                dp[i][j]=max(dp[i][j],q.front().m+j*a[i].P);
            }
            for(int j=a[i].S+a[i].L; j<=n; j++)
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
        int ans=0;
        for(int i=1; i<=n; i++) ans=max(ans,dp[k][i]);
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(poj1821 单调队列优化)