美梦1(JSOI2014,算法艺术与信息学竞赛)

【问题描述】

  这天晚上,约翰做了个奇怪的美梦。他拥有了分别分布在N座高高低低的山上的N个池塘,N座山连成一条直线,从左往右第i座山的高度是Hi。池塘中的鱼都是他请专家运用科学的方法专门养殖的,为了保护每个池塘的生态环境,他现在要在这N座山上建造若干个看护点。约翰是个很节约的人,在第i座山建造看护点的花费为Ci。假设在第i座山建造一个看护点,则往左或者往右第一座不比这座山低的山将挡住看护的视线。譬如说: {Hi} = {1 4 4 5 7 2}表示第一座山高度为1,第二座山高度为4。。。 如果在第1座山建造一个看护点,则可以看护第1,2两个池塘。如果在第5座山上建造一个看护点,则左右的池塘都能被看护到。如果在第3座山上建造一个看护点,则能够看护到第2,3,4个池塘。

Problem Task:

  要求能够看护到所有的池塘,建造看护点的最小代价是多少。即建造看护点的山对应的花费Ci之和最小。

Problem Input:

  第一行包含一个正整数N,N满足1<=N<=1000000。

  第二行包含N个正整数,第i个正整数Hi满足1<=Hi<=10^9,表示第i座山的高度

  第三行包含N个正整数,第i个正整数Ci满足1<=Ci<=10^9,表示在第i座山建造看护点的代价为Ci

Problem Output:

  一行包含一个正整数C,表示最小的代价。

Problem Input Example:

3

1 1 1

2 2 2

Problem output Example:

2

这题是个很裸的动归  , 不过数据范围有些怕人...

Way1:设f[i] 表示 看护1~i座山所需最小花费,则显然有f[i] = min{f[k] + C_t} (Lt<=k<=Rt = i)

不难发现可以用线段树维护最优值,单点修改,区间查询。

Way2: 设f[i] 表示 看护1~i座山,且第i座山上修建看护点 ,则显然有 f[i] = min{f[j]} + C_i (R_j >= L_i )

不难发现也可以偶那个线段树维护,单点查询,区间修改

Codes:

 1 #include<set>
 2 #include<queue>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<iostream>
 8 #include<algorithm>
 9 using namespace std;
10 const int N = 1000010;
11 typedef long long lld;
12 const lld inf = lld(21474836470000000);
13 #define Ch1 (i<<1)
14 #define Ch2 (Ch1|1)
15 #define For(i,n) for(int i=1;i<=n;i++)
16 #define Rep(i,l,r) for(int i=l;i<=r;i++)
17 #define Down(i,r,l) for(int i=r;i>=l;i--)
18 struct tnode{
19     int l,r,mid;
20     lld min;
21 }T[N<<2];
22 int Left[N],Right[N],top,n,H[N],C[N],st[N];
23 lld f[N];
24
25 void read(int &v){
26     int num = 0; char ch = getchar();
27     while(ch>‘9‘||ch<‘0‘) ch = getchar();
28     while(ch>=‘0‘&&ch<=‘9‘){
29         num = num * 10 + ch - ‘0‘;
30         ch = getchar();
31     }
32     v = num;
33 }
34
35 void init(){
36     read(n);
37     For(i,n) read(H[i]);
38     For(i,n) read(C[i]);
39     st[top=1] = 0;H[0] = H[n+1] = 2147483647;
40     For(i,n){
41         while(H[st[top]]<H[i]) top--;
42         Left[i] = max(st[top],1);
43         st[++top] = i;
44     }
45     st[top=1] = n+1;
46     Down(i,n,1){
47         while(H[st[top]]<H[i]) top--;
48         Right[i] = min(st[top],n);
49         st[++top] = i;
50     }
51 }
52
53 void Build(int l,int r,int i){
54     T[i].l = l;T[i].r = r;T[i].mid = (l+r)>>1;
55     T[i].min = inf;
56     if(l==r) return;
57     Build(l,T[i].mid,Ch1); Build(T[i].mid+1,r,Ch2);
58 }
59 vector< pair<int,int> > G[N];
60 //f[i] = min{f[t] + cost[k]}
61
62 void Modify(int i,int x,lld delta){
63     if(T[i].l==T[i].r){
64         T[i].min = delta;
65         return;
66     }
67     if(x<=T[i].mid)  Modify(Ch1,x,delta);
68     else             Modify(Ch2,x,delta);
69     T[i].min = min(T[Ch1].min,T[Ch2].min);
70 }
71
72 lld query(int l,int r,int i){
73     if(l<=T[i].l&&T[i].r<=r) return T[i].min;
74     if(r<=T[i].mid)  return query(l,r,Ch1);
75     if(l>T[i].mid)   return query(l,r,Ch2);
76     return min(query(l,T[i].mid,Ch1) , query(T[i].mid+1,r,Ch2));
77 }
78
79 int main(){
80     freopen("fish1.in","r",stdin);
81     freopen("fish1.out","w",stdout);
82     init();
83     Build(0,n,1);
84     Modify(1,0,0);
85     For(i,n){
86         G[Right[i]].push_back(make_pair(Left[i],C[i]));
87         G[i].push_back(make_pair(Left[i],C[i]));
88     }
89     For(i,n){
90         f[i] = inf;
91         for(int j = 0;j<G[i].size();j++)
92            f[i] = min(f[i],query(G[i][j].first-1,i,1) + G[i][j].second);
93         Modify(1,i,f[i]);
94     }
95     cout<<f[n]<<endl;
96     return 0;
97 }

美梦1(JSOI2014,算法艺术与信息学竞赛),布布扣,bubuko.com

时间: 2024-10-15 21:54:47

美梦1(JSOI2014,算法艺术与信息学竞赛)的相关文章

算法艺术与信息学竞赛书摘

<算法艺术与信息学竞赛>这本书我详细看了1.1.1.2.1.3,之后就看得不是很懂了,所以还是把摘要写出来,方便让我知道到底能学到什么. 第一章 算法与数据结构 “数据结构+算法=程序设计” 从理论分析和实际应用两方面阐述了算法与数据结构的基本知识. 1.1 概括的叙述了算法.数据结构.以及计算理论的一些概念. 1.2从实例出发,概括的介绍了一些基本算法,包括美剧.贪心.递归.递推. 1.3介绍基本数据结构,包括线性表队列.栈.树.二叉树.以及图遍历与拓扑排序. 1.4介绍了一些实用数据结构,

算法竞赛入门经典(第2版)+算法艺术与信息学竞赛pdf-高清版免费下载

下载地址:网盘下载备用地址:网盘下载 原文地址:https://www.cnblogs.com/hsqdboke/p/9783440.html

信息学竞赛一本通提高版AC题解—例题1.1活动安排

书中代码有误.书中为sort(a+1,a+n+1,Cmp). // // Created by yuxi on 19-1-13. // /* * * <信息学竞赛一本通-提高版>全部AC解答及解释 * * 第一部分 基础算法 * 第一章 贪心算法 * 例题1 活动安排 * */ #include <iostream> #include <algorithm> #include <fstream> #include <string> using n

程序算法艺术与实践之二:函数的渐近的界

众所周知,算法所需的时间应当是随着其输入规模增长的,而输入规模与特定具体问题有关.对大多数问题来说其最自然的度量就是输入中的元素个数.算法的运行时间是指在特定输入时所执行的基本操作数.我们可以得到关于一个关于输入规模n的所需时间的函数.然而可以进一步简化算法的时间分析,我们进行进一步抽象,首先,忽略每条语句的真实代价,通过运行时间的增长率来度量一个算法在时间方面的表现.我们只考虑公式的最高次项,并忽略它的常数系数.本博文主要介绍一些相关的数学知识即:函数的渐近的界的定义与性质.常用的证明方法.

最小割模型在信息学竞赛中的应用___读后的收获

在看了Amber的<最小割模型在信息学竞赛中的应用>后感觉到了自己的智障-- 我还是按照目录来,其实第一个子目录中我收获最大的还是01分数规划的内容. 01分数规划:给定n个条件,在其中选取一些条件,使得要求的目标函数达到最值. 通俗一点说:给定两个数组,a[i]表示选取i的收益,b[i]表示选取i的代价.如果选取i,定义x[i]=1否则x[i]=0.每一个物品只有选或者不选两种方案,求一个选择方案使得R=sigma(a[i]*x[i])/sigma(b[i]*x[i])取得最值,即所有选择物

程序算法艺术与实践:递归策略之递归,循环与迭代

众所周知,递归的实现是通过调用函数本身,函数调用的时候,每次调用时要做地址保存,参数传递等,这是通过一个递归工作栈实现的,同时影响效率的.递归是利用系统的堆栈保存函数当中的局部变量来解决问题的,而递归就是在栈处理栈上一堆的指针指向内存中的对象,这些对象一直不被释放,直到递归执行到最后一次后,才释放空间. 循环效率与递归效率 递归与循环是两种不同的解决问题的典型思路.当然也并不是说循环效率就一定比递归高,递归和循环是两码事,递归带有栈操作,循环则不一定,两个概念不是一个层次,不同场景做不同的尝试.

1123: 零起点学算法30——参加程序设计竞赛

1123: 零起点学算法30--参加程序设计竞赛 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 3045  Accepted: 1353[Submit][Status][Web Board] Description 每年我们都有不少同学去参加程序设计竞赛. 考虑到参赛名额的限制,我们的教练制定了以下规则: (1)如果等级分排名前6或者训练缺席次数不多于2次的队伍允许代表学校参赛 (2)如果等级分排

国王的游戏(华东师范大学-信息学竞赛学教案)

信息学竞赛学教案 [引入问题]:国王的游戏 恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这n位大臣排成一排,国王站在队伍的最前面.排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果.国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏

程序算法艺术与实践经典排序算法之Insertion Sort

插入排序(Insertion Sort)的基本思想是每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止. 基本思想与伪代码 经过j-1遍处理后,A[1..j-1]己排好序.第j遍处理仅将A[j]插入L[1..j-1]的适当位置,使得A[1..j]又是排好序的序列.要达到这个目的,我们可以用顺序比较的方法.首先比较A[j]和A[j-1],如果A[j-1]≤ A[j],则A[1..j]已排好序,第i遍处理就结束了:否则交换A[j]与A[j-1]的