AtCoder Grand Contest 067 F - Yakiniku Restaurants

Posted wolfycz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Grand Contest 067 F - Yakiniku Restaurants相关的知识,希望对你有一定的参考价值。

题目传送门: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;
}

以上是关于AtCoder Grand Contest 067 F - Yakiniku Restaurants的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Grand Contest 005

AtCoder Grand Contest 006

AtCoder Grand Contest 008 题解

AtCoder Grand Contest 025 Problem D

AtCoder Grand Contest 019

AtCoder Grand Contest 003