动态规划测试test20170518
来源:互联网 发布:类似皮影客的软件 编辑:程序博客网 时间:2024/05/19 14:56
题意:
一个长度为N的序列(每个元素是
题解:
二分答案。
能否破除b和a的关系呢?
考虑什么情况下必须捆绑在一起。
如果
所以考虑排序
然后剩下的就没有限制了,于是问题就变成,给出一个数列,(每个组a的最大值)的和不能超过limit,(各组内b的的和)的最大值最小。
然后一个单调队列优化DP,具体细节看代码。
想交OJ的话可以看这个SPOJ.com - Problem SEQPAR2
然后lcy大神用线段树,我跑了8.72s,而Ta却只要4s,线段树题解看Ta的吧:http://blog.csdn.net/never_see/article/details/72802369
代码:
#include <cstdio>#include <cstring>#include <algorithm>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))typedef long long LL;const int size = 50000+10;const LL INF = 0x7fffffff;int n,limit,q[size],a[size],b[size];int dp[size],p1[size],p2[size];bool check(int m) { int i,j=1,k,s=0,f=0,r=0; for(i=1; i<=n; i++) { s+=b[i]; while(s>m) s-=b[j++]; if(j>i) return 0; while(f<r and a[q[r-1]]<=a[i]) --r; while(f<r and q[f]<j) ++f; q[r++]=i; dp[i]=dp[j-1]+a[q[f]]; for(k=f+1; k<r; k++) dp[i]=Min(dp[i],dp[q[k-1]]+a[q[k]]); } return dp[n]<=limit;}bool cmp(int x,int y) { return b[x]<b[y];}int main() { int i, j, l, r, mid; freopen("gold.in","r",stdin); freopen("gold.out","w",stdout); scanf("%d%d", &n, &limit); for (i = 1; i <= n; ++i) scanf("%d%d", &a[i], &b[i]), p1[i] = p2[i] = i; std::sort(p1 + 1, p1 + n + 1, cmp); for (j = 1, i = n; i >= 1; --i) for (; j <= n && b[p1[j]] <= a[i]; ++j) p2[p1[j]] = i; for (i = 1, j = 1; i <= n; i = l, ++j) { a[j] = a[i]; b[j] = b[i]; for (l = i + 1, r = Max(p2[i], i); l <= r; ++l) { a[j] = Max(a[j], a[l]); b[j] += b[l]; r = Max(r, p2[l]); } } n = j - 1; for (l = 0, r = INF; l < r;) { mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } printf("%d\n", l); return 0;}
题解:
这个题目有两种做法,一种直接用斜率优化,另一种在斜率优化的基础上进行点分治优化。
然后这个题目在NOI2014上被加强了为购票,题目和做法差不多,可以参见这个题目的做法。
代码:
#include <cstdio>#include <cstring>#include <algorithm>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))typedef long long LL;const int N = 100000+10;const LL INF = 1LL<<60;int n,g[N],nxt[N<<1],v[N<<1],w[N<<1],ok[N<<1],tot=1,son[N],f[N];int size,now,fa[N],V[N];int q[N],anc[N],t;LL ans[N],d[N],W[N];inline int read(int &in) { in=0;char ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) in=in*10+ch-'0'; return in;}inline void add_edge(int x,int y,int z) { v[++tot]=y;w[tot]=z;nxt[tot]=g[x];ok[tot]=1;g[x]=tot;}inline int up(LL &x,LL y) { if(x>y) x=y; }inline double pos(int x,int y) { return (double)(ans[y]-ans[x])/(double)(d[y]-d[x]);}namespace my_self { inline void find_root(int x,int y) { son[x]=1;f[x]=0; for(int i=g[x];i;i=nxt[i]) if(ok[i] and v[i]!=y) { find_root(v[i],x);son[x]+=son[v[i]]; if(son[v[i]]>f[x]) f[x]=son[v[i]]; } if(size-son[x]>f[x]) f[x]=size-son[x]; if(f[x]<f[now]) now=x; } inline void erfen(int x) { int l=1,r=t-1,tmp=t,mid; while(l<=r) { mid=(l+r)>>1; if((double)V[x]<=pos(q[mid],q[mid+1])) r=(tmp=mid)-1; else l=mid+1; } up(ans[x],W[x]+ans[q[tmp]]-d[q[tmp]]*V[x]); } inline void dfs(int x) { W[x]+=d[x]*V[x]; for(int i=g[x];i;i=nxt[i]) if(v[i]!=fa[x]) d[v[i]]=d[fa[v[i]]=x]+w[i],dfs(v[i]); } inline void cal(int x,int y) { erfen(x); for(int i=g[x];i;i=nxt[i]) if(ok[i]&&v[i]!=y)cal(v[i],x); } inline void cal2(int x,int y) { up(ans[x],W[x]+ans[y]-d[y]*V[x]); for(int i=g[x];i;i=nxt[i]) if(ok[i]&&v[i]!=fa[x])cal2(v[i],y); } inline void solve(int x) { f[0]=size=son[x]; find_root(x,now=0); int root=now,ta; if(root!=x) { for(int i=g[root];i;i=nxt[i]) if(v[i]==fa[root]) { ok[i]=ok[i^1]=0,solve(x);break; } int i; for(ta=0,i=fa[root];;i=fa[i]) { anc[++ta]=i;if(i==x) break; } for(t=0;ta;q[++t]=anc[ta--]) while(t>1&&pos(anc[ta],q[t])<pos(q[t],q[t-1])) t--; if(root>1) erfen(root); while(t>1 and pos(root,q[t])<pos(q[t],q[t-1])) t--; q[++t]=root; for(int i=g[root];i;i=nxt[i]) if(ok[i]) cal(v[i],root); for(int i=g[root];i;i=nxt[i]) if(ok[i]) ok[i^1]=0,solve(v[i]); } else for(int i=g[x];i;i=nxt[i]) if(ok[i]) ok[i^1]=0,cal2(v[i],x),solve(v[i]); }}int main() { freopen("harbingers.in","r",stdin); freopen("harbingers.out","w",stdout); read(n); for(int i=1;i<n;i++) { int x,y,z;read(x);read(y);read(z); add_edge(x,y,z);add_edge(y,x,z); } for(int i=2;i<=n;i++) { int x;read(x);read(V[i]);W[i]=x;ans[i]=INF; } son[1]=n;my_self::dfs(1);my_self::solve(1); for(int i=2;i<=n;i++) printf("%lld ",ans[i]); return 0;}
原题APIO 2010特别行动队
斜率优化经典题
代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)typedef long long ll;const int maxn = 100000+10;using namespace std;int n,l,r;ll a,b,c,q[maxn],f[maxn],s[maxn];inline int 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;}inline double getk(int x,int y){ return (double)((f[x]+a*s[x]*s[x]-b*s[x])-(f[y]+a*s[y]*s[y]-b*s[y]))/(double)(s[x]-s[y]);}int main(){ n=read();a=read();b=read();c=read(); F(i,1,n) s[i]=s[i-1]+read(); l=r=1;q[1]=0; F(i,1,n) { while (l<r&&getk(q[l],q[l+1])>a*s[i]*2) l++; f[i]=f[q[l]]+a*s[q[l]]*s[q[l]]-b*s[q[l]]-a*s[i]*s[q[l]]*2+a*s[i]*s[i]+b*s[i]+c; while (l<r&&getk(q[r-1],q[r])<getk(q[r],i)) r--; q[++r]=i; } printf("%lld\n",f[n]); return 0;}
阅读全文
0 0
- 动态规划测试test20170518
- 动态规划测试test20170430
- 动态规划测试test20170506
- 动态规划测试test20170511
- 动态规划测试test20170520
- 动态规划测试test20170513
- 动态规划测试test20170525
- 动态规划测试3(test20170406)
- 【DP】TEST20170518
- 动态规划!!!动态规划!!!
- 卷积和动态规划的简单测试程序
- 5月6日动态规划测试解题报告
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 【机房重构】--职责链模式+策略模式 实现下机
- 1015: 二次方程的实根
- 算法设计与分析(15) -- Generate Parentheses(难度:Medium)
- jqueryMobile 按钮
- API(Calendar类)
- 动态规划测试test20170518
- 『ORACLE』移动数据(Directory Object)
- CGLib 介绍与原理
- Bmob的本地缓存用户注意事项
- 1016: 银行利率
- 关于抽象
- POJ3420_Quad Tiling_矩阵与递推
- 杭电1018 Big Number
- [bigdata-83] python3+图数据库neo4j 电话号码 身份证 黑名单 创建节点 标签 关系 增标记 增关系 查询pattern示例