10.10
思路:
很明显得状态定义以及转移关系
Dp[i][j]表示前i个人装饰前j个单位能得到的最大魅力度
Dp[i][j]=max(dp[i-1][k]+(j-k)*w);(k+1<=原始位置<=j)
经过变形,可以得到dp[i][j]=max(dp[i-1][k]-k*w)+j*w,对于每一个dp[i][j]来说,j是常量,而k是变量,故将dp[i-1][k]-k*w部分求max,而且根据条件,k是满足条件的连续长度内的数,可以用单调队列优化
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 200010
#define LL long long
using namespace std;
struct EE{
int len, b, pos;
}a[N];
int n, m;
int q[N >> 1], h, t;
LL f[105][N];
bool cmp(EE a, EE b){
return a.pos < b.pos;
}
bool check_h(int i, int j){
return j-q[h] > a[i].len;
}
bool check_t(int i, int k){
return f[i-1][k]-k*a[i].b > f[i-1][q[t-1]]-q[t-1]*a[i].b;
}
void solve(){
sort(a+1, a+m+1, cmp);
for(int i=1; i<=m; i++){
h = 1, t = 1;
for(int j=1; j<=n; j++)
f[i][j] = f[i-1][j];
int L = max(1, a[i].pos - a[i].len + 1);
int R = min(n, a[i].pos + a[i].len - 1);
for(int k=L-1; k<a[i].pos; k++){
while(h<t && check_t(i,k)) t--;
q[t++] = k;
}
for(int j=a[i].pos; j<=R; j++){
while(h<t && check_h(i,j)) h++;
int k = q[h];
f[i][j] = max(f[i][j], f[i-1][k] + (j-k) * a[i].b);
}
for(int j=R+1; j<=n; j++)
f[i][j] = max(f[i][j], f[i][j-1]);
}
cout << f[m][n] << endl;
}
int main(){
freopen("gift.in", "r", stdin);
freopen("gift.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i=1; i<=m; i++)
scanf("%d%d%d", &a[i].len, &a[i].b, &a[i].pos);
solve();
return 0;
}