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;
    }
    
  • 相关阅读:
    方法中的散列可变参数
    方法中的散列可变参数
    策略模式
    策略模式
    HashSet,TreeSet
    HashSet,TreeSet
    ArrayList和LinkedList
    ArrayList和LinkedList
    关于鼠标悬浮标签元素效果(CSS:cursor属性)
    关于鼠标悬浮标签元素效果(CSS:cursor属性)
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10071802.html
Copyright © 2011-2022 走看看