AtCoder Regular Contest 067 F - Yakiniku Restaurants
生活随笔
收集整理的這篇文章主要介紹了
AtCoder Regular Contest 067 F - Yakiniku Restaurants
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
有n個餐廳排成一排,第i個與第i+1個之間距離是Ai。
有m種食物,每種食物只能在一個餐廳里吃,第j種食物在第i個餐廳里吃的收益是$b[i][j]$.
選擇每種食物在哪個餐廳里吃,使收益減去走過距離最大(食物可以不按順序吃)。
?
顯然走過距離就是選擇的餐廳所在的區間的長度,讓f[i][j]表示選擇的餐廳所在的區間為i到j的最大收益。
對于每個b[i][j],求出左邊和右邊第一個比它大的位置l,r.
那么對于左端點在l+1~i,右端點在i~r-1的區間里第j種食物肯定在第i個餐廳吃。
相當于f的一個矩陣加,打標記+前綴和。
?
#include<bits/stdc++.h> #define N 5005 #define ll long long using namespace std; int n,m; int st[N],top; int a[N][205],l[N],r[N]; ll f[N][N]; void add(int x1,int y1,int x2,int y2,int z) {f[x1][y1]+=z;f[x2+1][y2+1]+=z;f[x1][y2+1]-=z;f[x2+1][y1]-=z; } ll sum[N]; int main() {scanf("%d%d",&n,&m);for(int i=2;i<=n;i++){int tmp;scanf("%d",&tmp);sum[i]=sum[i-1]+tmp;}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&a[i][j]);}}for(int i=1;i<=m;i++){memset(l,0,sizeof(l));memset(r,0,sizeof(r));top=0;for(int j=1;j<=n;j++){while(top&&a[st[top]][i]<=a[j][i])r[st[top--]]=j;st[++top]=j;}while(top)r[st[top]]=n+1,top--;for(int j=n;j>=1;j--){while(top&&a[st[top]][i]<a[j][i])l[st[top--]]=j;st[++top]=j;}for(int j=1;j<=n;j++){add(l[j]+1,j,j,r[j]-1,a[j][i]);}}ll ans=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){f[i][j]+=-f[i-1][j-1]+f[i-1][j]+f[i][j-1];if(j>=i)ans=max(ans,f[i][j]-sum[j]+sum[i]);}}cout<<ans<<endl;return 0; }
轉載于:https://www.cnblogs.com/ezyzy/p/7688425.html
總結
以上是生活随笔為你收集整理的AtCoder Regular Contest 067 F - Yakiniku Restaurants的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 框架应用 : Spring MVC -
- 下一篇: 多生产者多消费者问题