毒瘤DP
什么?你说这TM就是个提高题?
我好菜啊
冷静思考:
当我们考虑洗车的老哥时,一个洗衣店有明显的后效性:最大费用可行流 动态规划。
f(i,j,k)表示:区间i,j,价值不小于k的答案max的后缀。
pre(i,j,k)表示:区间i,j此时答案的实际k
fat(i,j,k)表示:区间i,j此时答案实际k的实际位置。
cnt(i,k)表示:i位置最大值可满足为k的后缀和
四个dp滚动维护
真是简单的提高组难度的题啊
#include<bits/stdc++.h>
using namespace std;
typedef int INT;
#define int int
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
x=0;
int f=1;
char ch=nc();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=nc();
}
x*=f;
}
const int N=51;
const int M=4001;
int n,m;
struct Node{
int l,r,c;
}a[M];
int mmp[M]={};
int cnt[N][M]={};
int dp[N][N][M]={};
int pre[N][N][M]={};//the actually k
int fat[N][N][M]={};//the k's pos
int ans[N]={};
void expend(int l,int r,int k){
// cout<<l<<" "<<r<<" "<<fat[l][r][k]<<'\n';
k=pre[l][r][k];
ans[fat[l][r][k]]=mmp[k];
if(l==r)
return;
if(fat[l][r][k]>l)expend(l,fat[l][r][k]-1,k);
if(fat[l][r][k]<r)expend(fat[l][r][k]+1,r,k);
}
INT main(){
read(n);
read(m);
for(int i=1;i<=m;i++){
read(a[i].l);
read(a[i].r);
read(a[i].c);
mmp[i]=a[i].c;
}
sort(mmp+1,mmp+1+m);
int len=unique(mmp+1,mmp+1+m)-1-mmp;
for(int i=1;i<=m;i++){
a[i].c=lower_bound(mmp+1,mmp+1+len,a[i].c)-mmp;
}
for(int L=n;L>=1;L--){
for(int R=L;R<=n;R++){
for(int i=L;i<=R;i++){
for(int j=1;j<=len;j++){
cnt[i][j]=0;
}
}
for(int i=1;i<=m;i++){
if(L<=a[i].l&&a[i].r<=R){
for(int j=a[i].l;j<=a[i].r;j++){
cnt[j][a[i].c]++;
}
}
}
for(int i=len-1;i>=1;i--){
for(int j=L;j<=R;j++){
cnt[j][i]+=cnt[j][i+1];
}
}
pre[L][R][len]=len;
for(int k=len;k>=1;k--){
int max_sum=-1;
int pos;
for(int i=L;i<=R;i++){
int l_sum=0;
int r_sum=0;
if(L<i)l_sum=dp[L][i-1][k];
if(i<R)r_sum=dp[i+1][R][k];
int sum=cnt[i][k]*mmp[k]+l_sum+r_sum;
if(sum>max_sum)max_sum=sum,pos=i;
}
dp[L][R][k]=max_sum;
fat[L][R][k]=pos;
if(k<len){
if(dp[L][R][k]<dp[L][R][k+1]){
dp[L][R][k]=dp[L][R][k+1];
pre[L][R][k]=pre[L][R][k+1];
}
else pre[L][R][k]=k;
}
}
}
}
cout<<dp[1][n][1]<<'\n';
/*for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)fat[i][i][j]=i;*/
expend(1,n,1);
// for(int i=1;i<=n;i++)
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
}