题解:P14439 [JOISC 2013] 考拉 / Koala
__EternalLife__ · · 题解
模拟赛 T2。
1
考虑 DP,定义
把起点和终点都看成
时间复杂度
2
考虑优化。
令
带回原式,有
则
注意到括号里的值与
动态开点的话时间复杂度为
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int maxn=1e5+10;
int K,M,D,A,N;
int T[maxn],B[maxn];
int a[maxn],b[maxn];
int dp[maxn];
struct Seg{
int l,r;
int max;
}tr[4*maxn];
void pushup(int id){
tr[id].max=max(tr[id<<1].max,tr[id<<1|1].max);
}
void build(int id,int l,int r){
tr[id].l=l; tr[id].r=r;
if(l==r){
tr[id].max=-1e18;
return;
}
int mid=(l+r)>>1;
build(id<<1,l,mid); build(id<<1|1,mid+1,r);
pushup(id);
}
void update(int id,int x,int k){
if(tr[id].l==tr[id].r){
tr[id].max=max(tr[id].max,k);
return;
}
int mid=(tr[id].l+tr[id].r)>>1;
if(x<=mid) update(id<<1,x,k);
else update(id<<1|1,x,k);
pushup(id);
}
int query(int id,int l,int r){
if(l<=tr[id].l&&tr[id].r<=r) return tr[id].max;
int mid=(tr[id].l+tr[id].r)>>1,maxx=-1e18;
if(l<=mid) maxx=max(maxx,query(id<<1,l,r));
if(mid<r) maxx=max(maxx,query(id<<1|1,l,r));
return maxx;
}
vector<int> vt;
int find(int x){
return lower_bound(vt.begin(),vt.end(),x)-vt.begin()+1;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>K>>M>>D>>A>>N;
for(int i=2;i<=N+1;i++) cin>>T[i]>>B[i];
T[1]=K; B[1]=0; T[N+2]=M; B[N+2]=0;
for(int i=1;i<=N+2;i++) a[i]=T[i]/D,b[i]=T[i]%D,vt.push_back(b[i]);
sort(vt.begin(),vt.end());
vt.erase(unique(vt.begin(),vt.end()),vt.end());
build(1,1,vt.size());
memset(dp,-0x3f,sizeof(dp));
dp[1]=0;
update(1,find(b[1]),A*a[1]);
for(int i=2;i<=N+2;i++){
int mx1=query(1,1,find(b[i])-1)-A;
int mx2=query(1,find(b[i]),vt.size());
dp[i]=B[i]-A*a[i]+max(mx1,mx2);
update(1,find(b[i]),dp[i]+A*a[i]);
}
cout<<dp[N+2];
return 0;
}
:::
3
赛时有人人类智慧过了,大致思路是按
但是你谷数据很强啊,目前乱搞做法最高也就拿了