[bzoj4658]rescue

来源:互联网 发布:建造者模式知乎 编辑:程序博客网 时间:2024/06/05 16:48

题目描述

wyh8000很喜欢看书,特别是那种很容易死脑细胞的书。
wyh8000看书喜欢从第K页开始看起,然后看到第M页,但是wvh8000并不是有耐心的小盆友,他
只想快点完成看书任务,然后就可以去愉快的农别人了,于是他经常跳着看,但是他一次最多跳D页,
然后阅读那一页的内容,然后死掉A的脑细胞。当然如果那一页的内容他比较感兴趣,又会回复一定
的脑细胞。
好心的学长不希望看到wyh8000的脑细胞死光,你能帮助wvh8000死掉尽可能少的脑细胞吗?

DP

关键点才有用嘛……
设f[i]表示看第i个关键点死的最少脑细胞。
f[i]=min(f[j]+TiTjDA)bi
这个DPn^2
然后该往哪个方向思考呢?你注意两个T同时+D相对关系还是不变,看来和模有关了。
把Ti表示为Ci*D+Ei(0<=Ei<D
然后发现原式变成
f[i]=min(f[j]+(CiCj+EiEjD)A)bi
只有Ei>Ej才产生1的贡献。
好咯,根据E为下标维护线段树即可。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=100000+10,maxtot=3500000+10,maxd=1e9;ll left[maxtot],right[maxtot];ll tree[maxtot];ll T[maxn],b[maxn],c[maxn],e[maxn];ll f[maxn];ll i,j,k,l,t,n,m,tot,root,A,D;ll read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}void change(ll &x,ll l,ll r,ll a,ll b){    if (!x) x=++tot,tree[x]=1e18;    if (l==r){        tree[x]=min(tree[x],b);        return;    }    ll mid=(l+r)/2;    if (a<=mid) change(left[x],l,mid,a,b);else change(right[x],mid+1,r,a,b);    tree[x]=min(tree[left[x]],tree[right[x]]);}ll query(ll x,ll l,ll r,ll a,ll b){    if (!x||a>b) return 1e18;    if (l==a&&r==b) return tree[x];    ll mid=(l+r)/2;    if (b<=mid) return query(left[x],l,mid,a,b);    else if (a>mid) return query(right[x],mid+1,r,a,b);    else return min(query(left[x],l,mid,a,mid),query(right[x],mid+1,r,mid+1,b));}int main(){    k=read();m=read();D=read();A=read();n=read();    fo(i,1,n) T[i]=read(),b[i]=read();    T[0]=k;T[++n]=m;    fo(i,0,n){        c[i]=T[i]/D;        e[i]=T[i]%D;    }    tree[0]=1e18;    change(root,0,D-1,e[0],-c[0]*A);    fo(i,1,n){        f[i]=1e18;        j=query(root,0,D-1,0,e[i]-1);        f[i]=min(f[i],j+A+c[i]*A-b[i]);        j=query(root,0,D-1,e[i],D-1);        f[i]=min(f[i],j+c[i]*A-b[i]);        change(root,0,D-1,e[i],f[i]-c[i]*A);    }    printf("%lld\n",-f[n]);}
0 0
原创粉丝点击