[Codevs] 3304 水果姐逛水果街

3304 水果姐逛水果街Ⅰ

 

 时间限制: 2 s
 空间限制: 256000 KB
 题目等级 : 钻石 Diamond
 
题目描述 Description

水果姐今天心情不错,来到了水果街。

水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。

学过oi的水果姐迅速发现了一个赚钱的方法:在某家水果店买一个水果,再到另外一家店卖出去,赚差价。

就在水果姐窃喜的时候,cgh突然出现,他为了为难水果姐,给出m个问题,每个问题要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去,求每个问题中最多可以赚多少钱。

 
输入描述 Input Description

第一行n,表示有n家店

下来n个正整数,表示每家店一个苹果的价格。

下来一个整数m,表示下来有m个询问。

下来有m行,每行两个整数x和y,表示从第x家店出发到第y家店。

 
输出描述 Output Description

有m行。

每行对应一个询问,一个整数,表示面对cgh的每次询问,水果姐最多可以赚到多少钱。

 

样例输入 Sample Input

10
2 8 15 1 10 5 19 19 3 5 
4
6 6
2 8
2 2
6 3

 

样例输出 Sample Output

0
18
0
14

 

数据范围及提示 Data Size & Hint

0<=苹果的价格<=10^8

0<n,m<=200000

 

分析 Analysis

偶遇菜菜qwq Orz CGH

这道题Tag线段树

心情极差直接思路

首先提出第一步思路:首先在建树的时候维护完整区间内的最优解

一般来说就是 Tree[rc].maxx - Tree[lc].minn (或者反过来)

然后根据题意我们知道 l 和 r 还可以翻来翻去的 --真好玩qwq-- 因为不可以Step Back所以需要保存两个顺序( --L->R / R->L--) 的最优解

(其实是根据WA知道的因为我第一次遇到这种情况直接强制 左端点 < 右端点 )

那么我们的线段树就有了如下元素:maxx minn ans1 ans2

其中maxx minn显然你们都懂的,ans1 保存从左到右时的最优解, ans2 保存从右到左时的最优解

接下来英勇地第二次WA

(按我这样初赛能过就不错了qwq)

仔细思考题意。

定义 [ ] 为操作区间,( ) 为查询区间,

( [     ] )  时,

答案 = max( Tree[当前结点].ans , Tree[右子树].maxx-Tree[左子树].minn )

[ (     ) ]  时,

答案 = max( 右子树中最大值-左子树中最小值 , 左子树中最优解 , 右子树中最优解 )

注意,第二种情况中没有用 Tree[ ] 

惟一一个关键点就在这

根据我的理解,第二种情况中的左右子树,并不是一个完整区间,而是被一分为二的询问的不完整的区间。

因此这次query函数并不单纯返回一个值,而是返回一段不完整区间,这段不完整区间囊括了该区间内整个的信息。

一遍AC = =

 

代码 Code

 1 #include<cstdio>
 2 #include<iostream>
 3 #define mid (L+R)/2
 4 #define lc (rt<<1)
 5 #define rc (rt<<1|1)
 6 #define maxn 100000
 7 using namespace std;
 8 
 9 int n,m,a,b;
10 const int inf = 0x3f3f3f3f;
11 
12 struct node{
13     int maxx,minn,ans1,ans2;
14     node(){
15         maxx = ans1 = ans2 = 0;
16         minn = inf;
17     }
18     
19 //    node(int a,int b,int c,int d){
20 //        maxx = a,minn = b,ans1 = c,ans3 = d;
21 //    }
22 }Tree[maxn*100];
23 
24 void maintain(int rt){
25     Tree[rt].maxx = max(Tree[lc].maxx,Tree[rc].maxx);
26     Tree[rt].minn = min(Tree[lc].minn,Tree[rc].minn);
27     Tree[rt].ans1 = max( Tree[rc].maxx-Tree[lc].minn , max(Tree[lc].ans1,Tree[rc].ans1) );
28     Tree[rt].ans2 = max( Tree[lc].maxx-Tree[rc].minn , max(Tree[lc].ans2,Tree[rc].ans2) );
29 }
30 
31 void build(int rt,int L,int R){
32     if(L == R){
33         scanf("%d",&Tree[rt].maxx);
34         Tree[rt].minn = Tree[rt].maxx;
35         Tree[rt].ans1 = Tree[rt].ans2 = 0;
36     }else{
37         build(lc,L,mid);
38         build(rc,mid+1,R);
39         
40         maintain(rt);
41     }
42 }
43 
44 node query(int rt,int L,int R,int qL,int qR){
45     if(qL <= L && R <= qR){
46         return Tree[rt];
47     }else{
48         node cnt;
49         
50         node LC,RC;
51         if(qL <= mid) LC = query(lc,L,mid,qL,qR);
52 //        else LC = (node){0,inf,0,0};
53         
54         if(qR > mid) RC = query(rc,mid+1,R,qL,qR);
55 //        else RC = (node){0,inf,0,0};
56         
57         cnt.maxx = max(LC.maxx,RC.maxx);
58         cnt.minn = min(LC.minn,RC.minn);
59         cnt.ans1 = max(max(LC.ans1,RC.ans1),RC.maxx-LC.minn);
60         cnt.ans2 = max(max(LC.ans2,RC.ans2),LC.maxx-RC.minn);
61         
62         return cnt;
63     }
64 }
65 
66 int main(){
67     scanf("%d",&n);
68     
69     build(1,1,n);
70     
71     scanf("%d",&m);
72     
73     for(int i = 1;i <= m;i++){
74         scanf("%d%d",&a,&b);
75         
76         if(a < b){
77             node ans = query(1,1,n,a,b);
78             printf("%d\n",ans.ans1);
79         }else{
80             node ans = query(1,1,n,b,a);
81             printf("%d\n",ans.ans2);
82         }
83     }
84     
85     
86     return 0;
87 }
心情极差,甚至想找男朋友qwq

 

posted @ 2017-08-29 19:19  Leviaton  阅读(142)  评论(0编辑  收藏  举报