モノトーンキュー最適化DP - WOJ#2735ホップスコッチ

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/weixin_42557561/article/details/102737198

ポータル


分析

ときNOIPの人気グループテストすると、DPはないでしょう
決定的に放棄され、直接、テストでこの質問を見ます

2年後、私は笑って/ようやく問題を理解することができました
はっきり二分法+ DP法的な判断であります

定義 F [ ] F [i]は、 iが利用可能な最大点の位置に到達示し
明らかです F [ ] = メートル A バツ F [ J ] + S C インクルード R E [ ] F [I] = MAX(F [J])+スコア[I]
J J 会います メートル A バツ 1 D g ) < = x [ i ] x [ j ] < = d + g MAX(1、DG)<= xの[I] -x [J] <= D + G
制限の唯一の後半場合、キューは直接単調であることができます

今、より多くの制限が前半考える
私たちは単調に、左へのポインタを維持することができるが、キュー制限値は、その後チームが出て最初の爆弾の後半部分を制限し、前半に会ったとされていることを確認

収穫:
単調なポップアップキューキューは一つだけ条件を満たすことができるたびに
、我々は他の方法で維持する別の状態にします
この方法は、[STO LSR妖精ORZ]非常に一般的な感じです

コード
#include<bits/stdc++.h>
#define in read()
#define re register
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<1)+(res<<3)+(ch^48);
		ch=getchar();
	}
	return f==1?res:-res;
}
const int N=5e5+10;
typedef long long ll;
int head,tail,q[N];
int n,d,K,x[N];
ll score[N],f[N];
bool check(int g){
	head=1;tail=0;f[0]=0;
	int up=d+g,down=max(1,d-g);
	int l=0;//传说中的指针 
	for(re int i=1;i<=n;++i){
		while(x[i]-x[l]>=down){
			while(head<=tail&&f[l]>f[q[tail]]) tail--;
			q[++tail]=l;
			l++;
		}
		while(head<=tail&&x[i]-x[q[head]]>up) head++;
		if(head<=tail) f[i]=f[q[head]]+score[i];
		else f[i]=-1e18;//如果无法到达设为-INF
	}
	ll ans=-1e18;
	for(re int i=0;i<=n;++i) ans=max(ans,f[i]);
	return ans>=K;
}
int main(){
	n=in;d=in;K=in;
	for(re int i=1;i<=n;++i) x[i]=in,score[i]=in;
	int l=0,r=1e9,ans=-1;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	cout<<ans;
	return 0;
}

おすすめ

転載: blog.csdn.net/weixin_42557561/article/details/102737198