agc007d

题目
思路:
首先发现由于两点经过时间固定,在收集完第一枚后,后面都是在吐出的瞬间收集,这样肯定是最优的。
又因为E最大,得出最优的收集方式是一段一段的先触发,再走回去,最后收集。
于是设\(dp_i\)表示收集完前i个硬币且回到\(x_i\)的最短时间
则:

\[dp_i <- dp_j+x_i-x_j+max(2(x_i-x_{j+1}),T) \]

然后将max拆开,因为max的临界点有单调性,所以可以直接单调队列优化。
之后就做完了。

这道题主要是观察到收集方式的规律,这种分割的方式在dp中很常见。

#include<bits/stdc++.h>
using namespace std;
struct FIO{static const int BUF_SIZE=1<<19;char _i[BUF_SIZE],*_1=_i,*_2=_i,_o[BUF_SIZE],*_t=_o;inline char _gt(){if(_1==_2){_1=_i;_2=_i+fread(_i,1,BUF_SIZE,stdin);}return _1==_2?EOF:*_1++;}inline void _pt(char c){if(_t-_o==BUF_SIZE){fwrite(_o,1,BUF_SIZE,stdout);_t=_o;}*_t++=c;}int _pr=6,le,_ob[20];template<typename T>FIO&operator>>(T&x){x=0;char c=_gt();bool sg=false;while(c!=EOF&&(c<'0'||c>'9')){if(c=='-')sg=true;c=_gt();}while(c!=EOF&&c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=_gt();}if(sg)x=-x;return*this;}FIO&operator>>(char*s){char c=_gt();while(c!=EOF&&c<33)c=_gt();while(c!=EOF&&c>=33)*s++=c,c=_gt();*s='\0';return*this;}FIO&operator>>(string&s){s.clear();char c=_gt();while(c!=EOF&&c<33)c=_gt();while(c!=EOF&&c>=33)s+=c,c=_gt();return*this;}FIO&operator>>(char&x){char c=_gt();while(c!=EOF&&c<33)c=_gt();x=c;return*this;}FIO&operator>>(double&x){x=0;char c=_gt();bool sg=0;while(c!=EOF&&c<33)c=_gt();if(c=='-'){sg=1;c=_gt();}while(c!=EOF&&c>='0'&&c<='9'){x=x*10+(c^48);c=_gt();}if(c=='.'){c=_gt();double tp=0.1;while(c!=EOF&&c>='0'&&c<='9'){x+=(c^48)*tp;tp*=0.1;c=_gt();}}if(sg)x=-x;return*this;}FIO&setprecision(int n){_pr=n<0?0:n;return*this;}template<typename T>FIO&operator<<(T x){if(x<0){_pt('-');x=-x;}if(x==0){_pt('0');return*this;}char _b[20];int ps=0;while(x>0){_b[ps++]=(x%10)^48;x/=10;}while(ps>0)_pt(_b[--ps]);return*this;}FIO&operator<<(const char*s){while(*s)_pt(*s++);return*this;}FIO&operator<<(const string&s){for(char c:s)_pt(c);return*this;}FIO&operator<<(char c){_pt(c);return*this;}FIO&operator<<(double x){if(x<0)_pt('-'),x=-x;if(isnan(x))return _pt('n'),_pt('a'),_pt('n'),*this;if(isinf(x))return _pt('i'),_pt('n'),_pt('f'),*this;long long ip=(long long)x;x-=ip;if(_pr==0){x*=10;if(x>=5)ip++;return*this<<ip;}le=0;_ob[0]=0;for(int i=1;i<=_pr;i++){x*=10;_ob[++le]=(int)x;x-=(int)x;}x*=10;int _tp=(int)x;if(_tp>=5){int j=le;_ob[le]++;while(_ob[j]==10)_ob[j-1]++,_ob[j]=0,j--;}ip+=_ob[0];*this<<ip<<".";for(int i=1;i<=le;i++)*this<<_ob[i];return*this;}~FIO(){fwrite(_o,1,_t-_o,stdout);}}fst;
#define cin fst
#define cout fst
typedef long long ll;
#define N 1000005
#define int long long
int n,e,t,x[N];
ll f[N];
int q[N],ql,qr;
signed main(){
	cin>>n>>e>>t;
	for(int i=1;i<=n;i++)cin>>x[i];
	memset(f,0x3f,sizeof(f));
	f[0]=0;
	ql=qr=1; ll g=0x3f3f3f3f3f3f3f3fll;
	for(int i=1;i<=n;i++){
		while(ql<=qr&&2*(x[i]-x[q[ql]+1])>t){
			g=min(g,f[q[ql]]-2*x[q[ql]+1]);
			ql++;
		}
		f[i]=min({f[i],f[q[ql]]+t,g+2*x[i]});
		q[++qr]=i;
	}
	cout<<f[n]+e<<'\n';
	return 0;;
}
posted @ 2026-09-11 21:08  whs_1007  阅读(6)  评论(0)    收藏  举报