• BZOJ4380: [POI2015]Myjnie


    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

    Sample Output

    43
    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;
    }
    

      

  • 相关阅读:
    逐步解析ASP.NET请求响应流程图(B/S IIS)
    UML类图表示
    aspnet_isapi.dll扩展注册
    .NET请求编译流程图(解释为什么第一次请求比较慢)
    前台线程和后台线程的区别
    IIS的内部原理
    is和as的区别
    Javascript限制多行文本输入框的字符数(转载)
    事件触发
    查看ASP.NET2.0编译后的源代码的方法
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5413982.html
Copyright © 2020-2023  润新知