P3089 [USACO13NOV] Pogo-Cow S

思路:

首先要先将目标点按照坐标从小到大排序。

考虑动态规划算法,定义 \(f_{i,j}\) 表示从 \(j \to i\) 的最大得分:

\[f_{i,j} = p_i + \max\limits_{k=i+1}^n [x_k-x_i \ge x_i - x_j] f_{k,i} \]

朴素实现是 \(O(N^3)\)但是数据过水,可以冲过去

考虑优化,注意一下 \([x_k-x_i \ge x_i - x_j]\) 的条件,即 \([x_k \ge 2x_i -x_j]\),则当 \(j\) 单增时,\(2x_i-x_j\) 单减,那么我们可以走指针维护 \(k\),维护中统计 \(f_{k,i}\) 的最大值即可。

时间复杂度为 \(O(N^2)\)

注意还可以往左走,状态方程类似,就不多说了。

完整代码:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=1010; 
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
          f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void write(ll x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>9)
	  write(x/10);
	putchar(x%10+'0');
}
struct Node{
	ll x,w;
	bool operator<(const Node&rhs)const{
		return x<rhs.x;
	}
}A[N];
ll n,ans,s;
ll a[N],b[N];
ll f[N][N],g[N][N];
bool End;
int main(){
	n=read();
	for(int i=1;i<=n;i++)
	  A[i]={read(),read()};
	sort(A+1,A+n+1);
	for(int i=1;i<=n;i++){
		a[i]=A[i].x;
		b[i]=A[i].w;
	}
	for(int i=1;i<=n;i++)
	  f[n][i]=b[n];
	for(int i=n-1;i>=1;i--){
		ll Max=0;
		for(int k=n,j=1;j<=i;j++){
			while(a[k]>=2ll*a[i]-a[j]&&k>=i+1){
				Max=max(Max,f[k][i]);
				k--;
			}
			f[i][j]=Max+b[i];
		}
	}
	g[1][1]=b[1];
	for(int i=1;i<=n;i++){
		ll Max=0;
		for(int j=1,k=n;k>=i+1;k--){
			while(a[j]<=2ll*a[i]-a[k]&&j<i){
				Max=max(Max,g[i][j]);
				j++;
			}
			g[k][i]=max({g[k][i],b[i]+b[k],Max+b[k]});	
		}
	}
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=i;j++)
	    ans=max({ans,f[i][j],g[i][j]});
	write(ans);
	cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
	return 0;
}
posted @ 2024-08-02 21:16  rgw2010  阅读(5)  评论(0编辑  收藏  举报