Description
有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]。
有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i],那么这个人就不洗车了。
请给每家店指定一个价格,使得所有人花的钱的总和最大。
Input
第一行包含两个正整数n,m(1<=n<=50,1<=m<=4000)。
接下来m行,每行包含三个正整数a[i],b[i],c[i](1<=a[i]<=b[i]<=n,1<=c[i]<=500000)
Output
第一行输出一个正整数,即消费总额的最大值。
第二行输出n个正整数,依次表示每家洗车店的价格p[i],要求1<=p[i]<=500000。
若有多组最优解,输出任意一组。
Sample Input
7 5
1 4 7
3 7 13
5 6 20
6 7 1
1 2 5
1 4 7
3 7 13
5 6 20
6 7 1
1 2 5
Sample Output
43
5 5 13 13 20 20 13
5 5 13 13 20 20 13
将所有c[i]离散,设f[l][r][j]表示[l,r]区间内,最小值>=j的收益。
设g[x][j]表示所有[l,r]中c[i]>=j的区间个数,即每个人的贡献,然后序列DP即可。
时间复杂度为O(N^3*M)
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=55; const int maxm=4005; int n,m,B[maxn],s[maxm],t[maxm],A[maxm],tmp[maxm]; int f[maxn][maxn][maxm],p[maxn][maxn][maxm],g[maxn][maxm]; void print(int l,int r,int j) { if(l>r) return; int x=p[l][r][j]; if(!x) print(l,r,j+1); else print(l,x-1,j),B[x]=tmp[j],print(x+1,r,j); } int main() { n=read();m=read(); rep(i,1,m) s[i]=read(),t[i]=read(),A[i]=tmp[i]=read(); sort(tmp+1,tmp+m+1); rep(i,1,m) A[i]=lower_bound(tmp+1,tmp+m+1,A[i])-tmp; dwn(l,n,1) rep(r,l,n) { rep(i,l,r) rep(j,1,m) g[i][j]=0; rep(j,1,m) if(l<=s[j]&&t[j]<=r) g[s[j]][A[j]]++,g[t[j]+1][A[j]]--; rep(i,l,r) rep(j,1,m) g[i][j]+=g[i-1][j]; rep(i,l,r) dwn(j,m,2) g[i][j-1]+=g[i][j]; dwn(j,m,1) { int& ans=f[l][r][j]; rep(x,l,r) { int res=f[l][x-1][j]+f[x+1][r][j]+tmp[j]*g[x][j]; if(res>=ans) p[l][r][j]=x,ans=res; } if(f[l][r][j+1]>ans) { ans=f[l][r][j+1]; p[l][r][j]=0; } } } printf("%d ",f[1][n][1]); print(1,n,1); rep(i,1,n) printf("%d%c",B[i],i==n?' ':' '); return 0; }