【線段樹】買水果
阿新 • • 發佈:2020-08-03
Description
水果姐今天心情不錯,來到了水果街。
水果街有n家水果店,呈直線結構,編號為1~n,每家店能買水果也能賣水果,並且同一家店賣與買的價格一樣。
學過oi的水果姐迅速發現了一個賺錢的方法:在某家水果店買一個水果,再到另外一家店賣出去,賺差價。
就在水果姐竊喜的時候,cgh突然出現,他為了為難水果姐,給出m個問題,每個問題要求水果姐從第x家店出發到第y家店,途中只能選一家店買一個水果,然後選一家店(可以是同一家店,但不能往回走)賣出去,求每個問題中最多可以賺多少錢。
Input
第一行n,表示有n家店
下來n個正整數,表示每家店一個蘋果的價格。
下來一個整數m,表示下來有m個詢問。
下來有m行,每行兩個整數x和y,表示從第x家店出發到第y家店。
Output
有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
Hint
0<=蘋果的價格<=10^8
1<=n,m<=200000
思路
- 線段樹記錄:最大值,最小值,從左往右的答案,從右往左的答案(兩個買賣水果點在兩個不同區間/相同區間,有點像旅館Hotel(USACO 2008 February Gold))
- 有可能從右往左走,所以answer=max{右區間的最大值-左區間的最小值/左區間的最大值-右區間的最小值,左區間的答案,右區間的答案}
程式碼
#include <iostream> #include <cstdio> #define maxn 200005 using namespace std; int n,m,v[maxn]; struct fdfdfd{int l,r,maxx,minn,ans1,ans2;}a[maxn<<2]; void pushup(int x) { a[x].maxx=max(a[x<<1].maxx,a[x<<1|1].maxx); a[x].minn=min(a[x<<1].minn,a[x<<1|1].minn); a[x].ans1=max(a[x<<1|1].maxx-a[x<<1].minn,max(a[x<<1].ans1,a[x<<1|1].ans1)); a[x].ans2=max(a[x<<1].maxx-a[x<<1|1].minn,max(a[x<<1].ans2,a[x<<1|1].ans2)); } void build(int x,int left,int right) { a[x].l=left; a[x].r=right; if(left==right){a[x].maxx=a[x].minn=v[left]; return;} int mid=(left+right)>>1; build(x<<1,left,mid); build(x<<1|1,mid+1,right); pushup(x); } fdfdfd query(int x,int left,int right) { if(a[x].l>right||a[x].r<left) return (fdfdfd){0,0,-1,0x7fffffff,-1,-1}; if(left<=a[x].l&&right>=a[x].r) return a[x]; fdfdfd temp1=query(x<<1,left,right),temp2=query(x<<1|1,left,right),temp; temp.ans1=max(max(temp1.ans1,temp2.ans1),temp2.maxx-temp1.minn); temp.ans2=max(max(temp1.ans2,temp2.ans2),temp1.maxx-temp2.minn); temp.minn=min(temp1.minn,temp2.minn); temp.maxx=max(temp1.maxx,temp2.maxx); return temp; } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&v[i]); build(1,1,n); scanf("%d",&m); while(m--) { int f1,f2; scanf("%d%d",&f1,&f2); if(f1==f2) puts("0"); else if(f1<f2) printf("%d\n",query(1,f1,f2).ans1); else printf("%d\n",query(1,f2,f1).ans2); } return 0; }