题意:给定 a [ i ] a[i] a[i]和 b [ i ] b[i] b[i],给个数的贡献是 [ a [ i ] , b [ i ] ] [a[i],b[i]] [a[i],b[i]]区间内不超过 c [ i ] c[i] c[i]的值中的最小值。
请给出最大值和每个贡献 p [ i ] p[i] p[i],使得最后的答案最大。
若存在多组随便输出一组就行。
为啥这题给放到区间DP
没看出来啊
I.普通DP
设 a s d [ i ] [ j ] asd[i][j] asd[i][j]表示 [ i , j ] [i,j] [i,j]所能提供的最大贡献。
但是这个方程很难转移
并且,由于转移的过程中还需要记录具体的取值,所以需要一个 q w e qwe qwe数组来记录
设 q w e [ i ] [ j ] qwe[i][j] qwe[i][j]表示区间 [ i , j ] [i,j] [i,j]中的最小值
并且上面的 [ i , j ] [i,j] [i,j]都是固定的(即题目给定的 a [ i ] a[i] a[i]和 b [ i ] b[i] b[i])
但是这道题需要在调整中寻找最优解
考虑再加一维。
设 a s d [ i ] [ j ] [ k ] asd[i][j][k] asd[i][j][k]表示区间 [ i , j ] [i,j] [i,j],最小值 ≥ k \geq k ≥k 所提供的最大贡献。
最终的答案就是 a s d [ 1 ] [ n ] [ 1 ] asd[1][n][1] asd[1][n][1]
q w e [ i ] [ j ] [ k ] qwe[i][j][k] qwe[i][j][k]表示区间 [ i , j ] [i,j] [i,j]中的最小值 ≥ k \geq k ≥k所造成的最优解的最小值的取值
一个结论:
一定存在一种方案,使得每家洗车店的价格 p ∈ c p\in c p∈c
一个转移:
a s d [ i ] [ j ] [ k ] = m a x ( a s d [ i ] [ j ] [ k + 1 ] , c o s t ( i , j , k ) ) asd[i][j][k]=max(asd[i][j][k+1],cost(i,j,k)) asd[i][j][k]=max(asd[i][j][k+1],cost(i,j,k))
其中cost(i,j,k)
表示
[
i
,
j
]
[i,j]
[i,j]的最小值正好取到
k
k
k时的最大贡献。
再用 v [ i ] [ j ] v[i][j] v[i][j]表示 i i i位置上容忍度 ≥ j \geq j ≥j的人数
最终的转移方程就是:
cost(i,j,k)=max(asd[i][p-1][k]+asd[p+1][j][k]+v[p][k]*k);
但是还需要输出方案
通过上面所描述的做法,我们只需要记录第三维转移的具体值 q w e qwe qwe和区间转移的具体位置 p p p 即可输出方案
#include<bits/stdc++.h>
using namespace std;
#define f1(a,b,c) for(int c=a;c<=b;c++)
#define f2(a,b,c) for(int c=a;c>=b;c--)
#define f3(a,b,c) for(int c=a;c;c=b)
#define so1(a,n) sort(a+1,a+n+1,mycmp);
#define so2(a,n) sort(a+1,a+n+1);
#define ll long long
#define itn int
#define ubt int
const int twx=5e3+100;
const int N=60;
const int inf=0x3f3f3f3f;
ll read()
{
ll sum=0;
ll flag=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
{
flag=-1;
}
c=getchar();
}
while(c>='0'&&c<='9')
{
sum=((sum*10)+c-'0');
c=getchar();
}
return sum*flag;
}
int n,m;
int a[twx];
int b[twx];
int c[twx];
int d[twx];
int ans[N];
int asd[N][N][twx];
int qwe[N][twx];
int h[N][N][twx];
int pre[N][N][twx];
void print(int l,int r,int p)
{
if(l>r)
{
return;
}
p=pre[l][r][p];
int k=h[l][r][p];
ans[k]=d[p];
print(l,k-1,p);
print(k+1,r,p);
return;
}
void init()
{
n=read();
m=read();
f1(1,m,i)
{
a[i]=read();
b[i]=read();
c[i]=d[i]=read();
}
so2(d,m)
int cnt=unique(d+1,d+m+1)-d-1;
f1(1,m,i)
{
c[i]=lower_bound(d+1,d+cnt+1,c[i])-d;
}
f1(1,n,len)
{
f1(1,n-len+1,i)
{
int j=i+len-1;
memset(qwe,0,sizeof qwe);
f1(1,m,k)
{
if(i<=a[k]&&b[k]<=j)
{
f1(a[k],b[k],p)
{
++qwe[p][c[k]];
}
}
}
f1(i,j,k)
{
f2(cnt,1,p)
{
qwe[k][p]+=qwe[k][p+1];
}
}
f2(cnt,1,k)
{
int MAX=0;
f1(i,j,p)
{
if(MAX<=asd[i][p-1][k]+asd[p+1][j][k]+qwe[p][k]*d[k])
{
MAX=asd[i][p-1][k]+asd[p+1][j][k]+qwe[p][k]*d[k];
h[i][j][k]=p;//记录转移位置
}
}
if(MAX>=asd[i][j][k+1])
{
asd[i][j][k]=MAX;
pre[i][j][k]=k;
}
else
{
asd[i][j][k]=asd[i][j][k+1];
pre[i][j][k]=pre[i][j][k+1];
}
}
}
}
printf("%d\n",asd[1][n][1]);
print(1,n,1);
f1(1,n,i)
{
printf("%d ",ans[i]);
}
}
void work()
{
}
void print()
{
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
init();
return 0;
}