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;}



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 做深蹲时膝盖总是吱吱响怎么办 爬山爬的膝盖疼怎么办 膝盖一吹风就疼怎么办 走路太多膝盖腿疼怎么办 膝盖一着凉就痛怎么办 月子里脚受凉了怎么办 膝关节受凉少量积液发胀怎么办 刮痧后吹空调了怎么办 200斤胖子膝盖痛怎么办 风扇吹的腿疼怎么办 膝盖受凉但不疼怎么办 刮痧后洗了澡怎么办 刮痧后喝了啤酒怎么办 艾灸后吃水果了怎么办 刮痧后能洗澡了怎么办 膝盖筋扭了肿了怎么办 骑行之后膝盖疼怎么办 膝盖软骨磨没了怎么办 腿上膝盖长骨刺怎么办 打羽毛球后膝盖疼怎么办 打完羽毛球膝盖疼怎么办 骑动感单车后膝盖痛怎么办 踩完动感单车右膝盖痛怎么办 跑步机走步损伤膝盖怎么办 健身把膝盖伤了怎么办 膝盖后面的腿窝筋酸疼怎么办 跳绳把膝盖伤了怎么办 鼻塞嗓子肿呼吸困难怎么办 鼻子内上火肿了怎么办 鼻子又红又肿怎么办 在公司班组人员不听话怎么办 熬了一夜睡不着怎么办 有人看我脚走路怎么办 穿牛仔裤裆部有三角怎么办 我的电脑打cffps不稳定怎么办 生米煮成了熟饭该怎么办 做完下蹲腿疼该怎么办 下蹲腿的筋酸痛怎么办 躺平了 腿酸痛怎么办 500上下蹲后腿痛怎么办 蹲完马步后站不起来怎么办?