斜率dp 入入门
来源:互联网 发布:电脑绘画卡通人物软件 编辑:程序博客网 时间:2024/05/22 12:36
A - Print Article HDU - 3507
题意:一台老旧的打字机,每打出一个单词就会有一个ci.输出一行的费用为
分析:dp[i]:前i个单词输出的最少费用
时间复杂度为n*n,n的范围是5e5,会T
这个时候就需要优化了,把min的范围变小就好了。
假设k< j < i,j比k优,则可以得到
设
g(j,k)=yj-yk/(xj-xk),如果g(j,k)<=sum[i],则j比k优,那么k就可以去掉了
如果g(i,j) < g(j,k)
if(g(j,k)<=sum[i]) 表示i比j优,j比k优,j,k可以去掉
if(g(i,j)>sum[i]) 表示j比i优,k比j优,i,j可以去掉
综合之上,if(g(i,j)< g(j,k)) 则j可以去掉
用队列维护,这样的话,我们没去掉的点,也就是队列中的点连起来就是下凸形。
因为g(i,j)相当于斜率,也就是一阶导,当任意g(j,k)<=g(i,j),也就是二阶导大于或者等于0.这个时候,函数呈上凹也就是下凸形
#include <iostream>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>using namespace std;#define ll long longconst int maxn = 5e5+10;ll dp[maxn],q[maxn],sum[maxn];ll y(int j,int k){ return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];}ll x(int j,int k){ return 2*(sum[j]-sum[k]);}ll getdp(int i,int j){ return dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j]);}int main(){ ll n,m; while(scanf("%I64d %I64d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) scanf("%I64d",&sum[i]); sum[0]=dp[0]=0; for(int i=1;i<=n;i++) sum[i]+=sum[i-1]; int head=0,tail=0; q[tail++]=0; for(int i=1;i<=n;i++) { while(head+1<tail&&y(q[head+1],q[head])<=sum[i]*x(q[head+1],q[head])) head++; dp[i]=getdp(i,q[head])+m; while(head+1<tail&&y(i,q[tail-1])*x(q[tail-1],q[tail-2])<=y(q[tail-1],q[tail-2])*x(i,q[tail-1])) tail--; q[tail++]=i; } printf("%I64d\n",dp[n]); } return 0;}
ps:做题做着做着,忽然想队列优化while判断中,能不能直接用getdp()来表示呢,那样就不用化简了,这样
while(head+1<tail&&getdp(i,q[head+1])<=getdp(i,q[head])) head++; dp[i]=getdp(i,q[head])+m; while(head+1<tail&&getdp(i,q[tail-2])*getdp(i,i)<=getdp(i,q[tail-1])*getdp(i,q[tail-1])) tail--;
第一个while还可以改,但是第二个就不行了呀,因为g(j,k)和i并没有关系,不能直接用i。
2016年沈阳区域赛I 题 The Elder UVALive - 7620
题意:给你一棵树,节点从1到n,代表n个城市。1是首都,现在要从每个城市分别送信到首都。邮差可以在中途经过的城市选择继续送信或者给别的邮差送,继续送信的时间是
分析:就是斜率dp嘛
状态转移:
这里有一点不同,就是这个斜率dp是在树上的,要注意还原。。。
#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <string>#include <cmath>#include <queue>#include <set>#include <map>#include <stack>//#pragma comment(linker,"/STACK:102400000,102400000")#define IN freopen("D:\\in.txt","r",stdin)#define OUT freopen("D:\\out.txt","w",stdout)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define inf 2147493647using namespace std;const int maxn = 1e5+10;int n;ll p;struct point{ int pos,time,z;};stack<point> st;struct node{ int pre,to;ll w;}e[maxn*2];int head[maxn],vis[maxn],q[maxn];ll dp[maxn],sum[maxn];int head1=0,tail=0;void init(){ mem(head,-1);mem(vis,0);mem(e,0);mem(sum,0);mem(dp,0);}void addedge(int h,int from,int to,ll w){ e[h].to=to;e[h].pre=head[from];e[h].w=w;head[from]=h;}ll y(int j,int k){ return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];}ll x(int j,int k){ return 2ll*(sum[j]-sum[k]);}ll getdp(int i,int j){ return dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+p;}int dfs_num=0;void dfs(int u){ int ti=++dfs_num; while(head1+1<tail&&y(q[head1+1],q[head1])<=sum[u]*x(q[head1+1],q[head1])) head1++; dp[u]=getdp(u,q[head1]); while(head1+1<tail&&y(u,q[tail-1])*x(u,q[tail-2])<=y(u,q[tail-2])*x(u,q[tail-1])){ tail--; point a; a.pos=tail; a.time=dfs_num; a.z=q[tail]; st.push(a); } q[tail++]=u; int nowhead1=head1,nowtail=tail; for(int i=head[u];i>-1;i=e[i].pre) { if(vis[e[i].to]) continue; vis[e[i].to]=1; head1=nowhead1,tail=nowtail; while(!st.empty()) { point t=st.top(); if(t.time<=ti) break; q[t.pos]=t.z; st.pop(); } sum[e[i].to]=sum[u]+e[i].w; dfs(e[i].to); }}int main(){ int T; scanf("%d",&T); while(T--) { init(); int h=0; scanf("%d %lld",&n,&p); for(int i=0;i<n-1;i++) { int from,to;ll w; scanf("%d %d %lld",&from,&to,&w); addedge(h,from,to,w);h++; addedge(h,to,from,w);h++; } vis[1]=1; while(!st.empty()) st.pop(); head1=0,tail=0; dfs_num=0; dp[1]=-p; for(int i=head[1];i>-1;i=e[i].pre) { if(vis[e[i].to]) continue; vis[e[i].to]=1; sum[e[i].to]=sum[1]+e[i].w; while(!st.empty()) st.pop(); head1=0,tail=0; q[tail++]=1; dfs(e[i].to); } ll ans=0; for(int i=1;i<=n;i++) ans=max(ans,dp[i]); cout<<ans<<endl; } return 0;}
- 斜率dp 入入门
- hdu3507 斜率优化dp入门
- 期望dp 入入门
- hdu 3507 斜率优化dp 入门学习
- hdu 2993 斜率优化 dp 入门学习
- hdu3507之斜率优化DP入门
- hdu 3507 斜率优化DP入门题
- hdu 3507 斜率优化dp入门
- 【HDU3507】Print Article-DP斜率优化入门
- [hdu3507] Print Article DP斜率优化入门
- 斜率dp
- hdu 2993 MAX Average Problem(DP+斜率优化入门题)
- hdu 2993 MAX Average Problem (斜率优化dp入门)
- HDU 3507 Print Article(斜率DP入门理解)
- HDU 3507 Print Article DP(斜率优化入门)
- Print Article HDU 3507(斜率DP入门模板题)
- Hdu 3507 Print Article【斜率优化Dp入门】
- Bzoj 1010[HNOI2008]玩具装箱toy【斜率优化Dp入门】
- 火狐浏览器Firefox 如何使用iMacros 自动填写网页表单
- 系统重装 Ghost系统的disk to image等等是什么意思
- Navicat for MySQL如何导入SQL文件
- Navicat for MySQL出现#1045 错误怎么办
- 用construct2做屬於自己的小遊戲
- 斜率dp 入入门
- Navicat for MySQL无法连接到数据库怎么办
- JAVA_如何复制项目
- HTML的DIV如何实现水平居中
- HTML的DIV如何实现垂直居中
- JAVA_the user operation is waiting怎么办
- Linux如何更新软件源
- Linux 将一般的用户加入sudo组is_not_in_the_sudoers_file._This_incident_will_be_reported解决方法
- 火狐浏览器Firefox 如何下载网页的SWF视频,硅谷动力的网站视频怎么下载