ZOJ 3632 Watermelon Full of Water(单点更新,区间查询)
来源:互联网 发布:国密算法的优势 编辑:程序博客网 时间:2024/06/13 16:52
题意:有n天,每天都可以买西瓜,每个西瓜的价格是ai,每个西瓜能吃bi天。问这n天每天都有西瓜吃的最小的代价是多少?如果你在第i天买了一个西瓜,那么之前买的西瓜就要全部扔掉,才能开始吃新的西瓜。
定义dp[i]为到i天为止,每天都有西瓜吃的最小代价,那么状态转移方程就是:dp[i]=min(dp[i],dp[i-k-1]+a[i-k])。这样时间复杂度会达到O(n^2),所以要优化。在递推的过程中,我们达到第i-k天之后,去更新第i-k+1天到第i天的代价。如果我们能一次性更新这些范围,就可以将复杂度降下来,优化的方法就是线段树。
转化的方法还是挺巧妙的。对于第i-k天,我们只去更新第i天这个点,然后在查询的时候,我们查询的是第i天到第n天里的最小值,因为如果我们得到的是在第i天到 第n天的某一个最小值,那么这个最小值一定是在第i天或第i-1天前更新到的。可以仔细想想。
#include <iostream>#include <cstdio>using namespace std;typedef long long LL;#define INF ((LL)1<<60)const int N=50005;int day[N],valu[N];LL dp[N];struct node{int left,right;LL imin;int mid(){return left+(right-left)/2;}void change(LL valu){imin=min(imin,valu);}};struct Segtree{node tree[N*4];void build(int left,int right,int ind){tree[ind].left=left;tree[ind].right=right;tree[ind].imin=INF;if(left!=right){int mid=tree[ind].mid();build(left,mid,ind*2);build(mid+1,right,ind*2+1);}}void updata(int pos,int ind,LL valu){if(tree[ind].left==tree[ind].right) tree[ind].change(valu);else {int mid=tree[ind].mid();if(pos<=mid) updata(pos,ind*2,valu);else updata(pos,ind*2+1,valu);tree[ind].imin=min(tree[ind*2].imin,tree[ind*2+1].imin);}}LL query(int be,int end,int ind){int left=tree[ind].left,right=tree[ind].right;if(be<=left&&right<=end) return tree[ind].imin;else {int mid=tree[ind].mid();LL imin1=INF,imin2=INF;if(be<=mid) imin1=query(be,end,ind*2);if(end>mid) imin2=query(be,end,ind*2+1);return min(imin1,imin2);}}}seg;int main(){int n;while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++) scanf("%d",&valu[i]);for(int i=1;i<=n;i++) scanf("%d",&day[i]);dp[0]=0;seg.build(1,n,1);for(int i=1;i<=n;i++){int pos=i+day[i]-1;if(pos>n) pos=n;seg.updata(pos,1,dp[i-1]+valu[i]);dp[i]=seg.query(i,n,1);}printf("%lld\n",dp[n]);}return 0;}
也可以用单调队列优化
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;typedef long long LL;const int N=50005;int data[N],day[N];LL dp[N];struct node{LL valu,ind;node(){}node(LL a,LL b){valu=a;ind=b;}bool operator<(const node &b)const{return valu>b.valu||(valu==b.valu&&ind>b.ind);}};int main(){int n;while(scanf("%d",&n)!=EOF){for(int i=1;i<=n;i++) scanf("%d",&data[i]);for(int i=1;i<=n;i++) scanf("%d",&day[i]);dp[0]=0;priority_queue<node> que;for(int i=1;i<=n;i++){node tmp=node(dp[i-1]+data[i],i+day[i]-1);while(!que.empty()&&que.top().ind<i) que.pop();que.push(tmp);dp[i]=que.top().valu;}printf("%lld\n",dp[n]);}return 0;}
- ZOJ 3632 Watermelon Full of Water(单点更新,区间查询)
- BNU Watermelon Full of Water-单点更新,区间询问
- ZOJ 3632 Watermelon Full of Water (线段树 区间更新 + dp)
- zoj 3632 Watermelon Full of Water
- ZOJ 3632 Watermelon Full of Water(SPFA)
- ZOJ 3632 Watermelon Full of Water 线段树
- zoj 3632 Watermelon Full of Water(DP+线段树)
- Zoj 3632 Watermelon Full of Water 优先队列
- Watermelon Full of Water - ZOJ 3632 dp+线段树
- ZOJ-3632 Watermelon Full of Water 线段树+DP
- ZOJ 3632 Watermelon Full of Water(dp+线段树或单调队列优化)
- ZJU 3632 - Watermelon Full of Water
- TOJ 4369 ZOJ 3632 Watermelon Full of Water / 线段树优化DP
- zoj (单点更新区间查询:线段树)
- zoj3632 Watermelon Full of Water 线段树,dp
- spoj375 树链剖分(单点更新,区间查询)
- LightOj1080Binary Simulation(区间更新单点查询)
- 模式二(区间更新,单点查询)
- js中String转Array
- 从子页面获取父页面的值
- UITableview 去除滑动删除 编辑状态删除
- 使用XMLSerialize 序列化和反序列化
- Java Script
- ZOJ 3632 Watermelon Full of Water(单点更新,区间查询)
- 最近要学习dfb积累资料
- N皇后问题
- Java web开发学习规划
- 基于nginx的tomcat负载均衡和集群
- java判定数组或集合是否存在某个元素
- SQL 参数化示例
- 4个Web图片在线压缩优化工具
- python 的函数