zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 067 F

    题目传送门:https://arc067.contest.atcoder.jp/tasks/arc067_d

    题目大意:

    (N)家烧烤店,在直线上按顺序排列,第(i)家烧烤店和第(i+1)家烧烤店的距离为(A_i)。你有(M)张烧烤券,在第(i)家烧烤店使用第(j)张券可以获得(B_{i,j})的快乐,你可以在某家烧烤店使用多张券。你现在可以从某个烧烤店开始,使用所有的券,使得你的快乐值减去所走路程最大


    我们考虑每个(B_{i,j})的贡献,我们找到第一个一个(B_{L,j}>B_{i,j})(L<i),然后(R)类似,那么(B_{i,j})对答案有贡献需要决策左端点在((L,i])中,右端点在([i,R))

    于是我们可以设(f_{l,r})表示决策在([l,r])的收益,对于每个(B_{i,j}),我们对(f_{(L,i],[i,R)})加上(B_{i,j})的贡献,可以证明,对于某张券(j)(B_{1sim n,j})对答案的贡献矩阵没有交集,因此我们可以用二维差分解决,最后还原(f)即可

    /*problem from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-');
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=5e3,M=2e2;
    int L[M+10][N+10],R[M+10][N+10],B[M+10][N+10],stack[N+10];
    ll sum[N+10][N+10],A[N+10];
    int main(){
    	int n=read(),m=read(); ll Ans=0;
    	for (int i=2;i<=n;i++)	A[i]=read()+A[i-1];
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			B[j][i]=read();
    	for (int i=1;i<=m;i++){
    		for (int j=1,top=0;j<=n;j++){
    			while (top&&B[i][stack[top]]<B[i][j])	top--;
    			L[i][j]=top?stack[top]+1:1;
    			stack[++top]=j;
    		}
    		for (int j=n,top=0;j>=1;j--){
    			while (top&&B[i][stack[top]]<B[i][j])	top--;
    			R[i][j]=top?stack[top]-1:n;
    			stack[++top]=j;
    		}
    		for (int j=1;j<=n;j++){
    			sum[L[i][j]][j]+=B[i][j];
    			sum[L[i][j]][R[i][j]+1]-=B[i][j];
    			sum[j+1][j]-=B[i][j];
    			sum[j+1][R[i][j]+1]+=B[i][j];
    		}
    	}
    	for (int i=1;i<=n;i++){
    		for (int j=1;j<=n;j++)	sum[i][j]+=sum[i][j-1];
    		for (int j=1;j<=n;j++)	sum[i][j]+=sum[i-1][j];
    		for (int j=i;j<=n;j++)	Ans=max(Ans,sum[i][j]-A[j]+A[i]);
    	}
    	printf("%lld
    ",Ans);
    	return 0;
    }
    
  • 相关阅读:
    JavaScript Patterns 5.7 Object Constants
    JavaScript Patterns 5.6 Static Members
    JavaScript Patterns 5.5 Sandbox Pattern
    JavaScript Patterns 5.4 Module Pattern
    JavaScript Patterns 5.3 Private Properties and Methods
    JavaScript Patterns 5.2 Declaring Dependencies
    JavaScript Patterns 5.1 Namespace Pattern
    JavaScript Patterns 4.10 Curry
    【Android】如何快速构建Android Demo
    【Android】如何实现ButterKnife
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10071802.html
Copyright © 2011-2022 走看看