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的主要内容,如果未能解决你的问题,请参考以下文章