zoukankan      html  css  js  c++  java
  • Codeforces1304F Animal Observation

    Description

    link

    大意:

    给你一个 (n imes m)的矩形,每一个格子里面有一个数字,你可以在每一行里选择一个 (2 imes k) 的矩形(这个矩形跨越两行),要求最后所有你选择的矩形的并的权值和最大。

    Solution

    这俩 (F) 题可以用一种标准解法完成(线段树或单调队列优化 (dp)

    首先要看出来这个是一个 (dp) 题(这一步应该很好想到把)

    然后想到要容斥,就是要先算总的(不考虑覆盖只算一次)减去覆盖的值

    (S_{i,j}) 为第 (i) 行的前缀和

    然后枚举我们当前选择的区间,就有转移方程

    这里和谐了,博主不会打大括号……或者参考wucstdio's solution

    (其实就是用 (g) 维护一个去掉重复的,然后用 (f) 再添上新增的)

    然后我们发现这样算复杂度是 (O(nm^2)) 的,我们并不能接受

    然后我们更改一下需要维护的量,让线段树去维护它就好了

    (O(nm space logm))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar(); 
    		return res*f;
    	}
    	const int N=1e5+10;
    	struct tree{
    		int maxx[N<<2]; 
    		#define maxx(p) maxx[p]
    		inline void push_up(int p){return maxx(p)=max(maxx(p<<1),maxx(p<<1|1)),void();}
    		inline void change(int p,int l,int r,int x,int d)
    		{
    			if(l==r) return maxx(p)=d,void();
    			int mid=(l+r)>>1; if(x<=mid) change(p<<1,l,mid,x,d); else change(p<<1|1,mid+1,r,x,d);		
    			return push_up(p),void();
    		}
    		inline int ask(int p,int l,int r,int L,int R)
    		{
    			if(R<L) return -1e15-10;
    			if(L<=l&&r<=R) return maxx(p);
    			int mid=(l+r)>>1,ans=-1e15-10;
    			if(L<=mid) ans=max(ans,ask(p<<1,l,mid,L,R));
    			if(R>mid) ans=max(ans,ask(p<<1|1,mid+1,r,L,R));
    			return ans;
    		}
    	}t1,t2,t3;
    	int n,m,l,a[55][20010],s[55][20010],f[20010];
    	signed main()
    	{
    		n=read(); m=read(); l=read();
    		for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) a[i][j]=read(),s[i][j]=s[i][j-1]+a[i][j];
    		for(int i=1;i<N;++i) t1.maxx[i]=t2.maxx[i]=t3.maxx[i]=-1e15-10;
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j+l-1<=m;++j)
    			{
    				f[j]=max(t1.ask(1,1,m,1,j-l),t1.ask(1,1,m,j+l,m));
    				f[j]=max(f[j],t2.ask(1,1,m,j-l+1,j)+s[i][j-1]);
    				f[j]=max(f[j],t3.ask(1,1,m,j+1,j+l)-s[i][j+l-1]);
    				if(f[j]<0) f[j]=0;
    			}
    			for(int j=1;j+l-1<=m;++j)
    			{
    				f[j]=f[j]+s[i][j+l-1]-s[i][j-1]+s[i+1][j+l-1]-s[i+1][j-1];
    				t1.change(1,1,m,j,f[j]); 
    				t2.change(1,1,m,j,f[j]-s[i+1][j+l-1]); 
    				t3.change(1,1,m,j,f[j]+s[i+1][j-1]);
    			}
    		} printf("%lld
    ",t1.ask(1,1,n,1,n));
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    
  • 相关阅读:
    【Lintcode】91 最小调整代价
    【LintCode】29 交叉字符串
    十二、动态规划
    HttpClient的简单使用
    ajax跨域请求
    session共享
    八大排序算法
    MAC 脚本批量启动应用
    知识点整理-bio、nio的简单demo
    知识点整理-数组如何实现随机访问?
  • 原文地址:https://www.cnblogs.com/yspm/p/12319112.html
Copyright © 2011-2022 走看看