tot=30+0+10=40
T1
- 脑筋急转弯
- 每一轮有些数会向左移动一格
- 答案就是max{i-a[i]}
T3
Solution
- 把上面的式子拆开变成
- F[i]=max{F[j]+Tj*A/D}-Ti*A/D+Bi-A
- F[i]=max{F[j]+Tj*A/D}-Ti*A/D+Bi
- 由于把向上取整拆开了
- 所以Tj的余数不同状态转移方程也不同
- 根据余数分类,查询时分类讨论
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define ll long long
using namespace std;
const ll N=1e6+100;
ll s,t,d,a,n,x,v,j,root,tot=0,cnt=0,minn[N<<2],lc[N<<2],rc[N<<2],pl[N],k[N],b[N],f[N];
void update(ll &o,ll L,ll R,ll x,ll val){
if(!o)o=++tot;
ll M=L+R>>1;
if(L==R){
minn[o]=min(minn[o],val);
return;
}
if(x<=M)update(lc[o],L,M,x,val);
else update(rc[o],M+1,R,x,val);
minn[o]=min(minn[lc[o]],minn[rc[o]]);
}
ll query(ll &o,ll L,ll R,ll ql,ll qr){
if(!o)return 1e15;
if(ql<=L&&R<=qr)return minn[o];
ll M=L+R>>1;
ll ans=1e15;
if(ql<=M)ans=min(ans,query(lc[o],L,M,ql,qr));
if(M<qr)ans=min(ans,query(rc[o],M+1,R,ql,qr));
return ans;
}
int main()
{
freopen("reading.in","r",stdin);
freopen("reading.out","w",stdout);
memset(f,0x3f,sizeof(f));
memset(minn,0x3f,sizeof(minn));
scanf("%lld%lld%lld%lld%lld",&s,&t,&d,&a,&n);
k[0]=s/d,b[0]=s%d;;
rep(i,1,n){
scanf("%lld%lld",&x,&v);
k[i]=x/d,b[i]=x%d;
pl[i]=v;
}
k[++n]=t/d,b[n]=t%d;
update(root,0,d-1,b[0],-k[0]*a);
rep(i,1,n){
j=query(root,0,d-1,0,b[i]-1);
f[i]=min(f[i],j+a+k[i]*a-pl[i]);
j=query(root,0,d-1,b[i],d-1);
f[i]=min(f[i],j+k[i]*a-pl[i]);
update(root,0,d-1,b[i],f[i]-a*k[i]);
}
cout<<-f[n];
return 0;
}