題目鏈結
首先,我們先假設這道題不需要修改物價,那麼我們如何找到最好的情況呢?
差分。如下數列:
1 4 3 5 2
很容易觀察出,在第乙個商店到第二個商店中,我們最多可以賺3元,在第乙個商店進貨,第二個商店賣出。
但是在第二個商店到第三個商店的途中,我們不能賺錢。因為第二個商店的**比第三個商店的**的**大,所以最優的情況是不進行買賣操作。
所以我們第乙個商店到第三個商店最多能賺多少呢?即是在第乙個商店買,第二個商店賣,在第三個商店不進行操作。
那麼對於第乙個商店到第四個商店,最多賺4元。但4=3+0+1,即選擇在第乙個商店買,第二個商店又買又賣,第三個商店不進行操作,第四個商店又賣;
所以就是差分了。
定義a[i],存放每個商店的**;
定義sum[i],表示由第i到i+1最多可以賺的錢數;
sum[i]=max(0,a[i+1]-a[i]);
因為如果a[i]>a[i+1],那麼最優操作是不進行買賣,也就是賺0元。
最後的答案就是求差分陣列的和了。
值得注意的是,在這道題中,從i走到j和從j走到i是不一樣的意思的,所以需要兩個差分陣列;
對於差分陣列,可以用線段樹維護。
現在我們來想一下如何進行改變值的操作。
設:a[i]改變了,只會影響 a[i
]−a[
i+1]
,a[i
+1]−
a[i]
,a[i
]−a[
i−1]
a[i] - a[i+1], a[i+1] - a[i],a[i] - a[i-1]
a[i]−a
[i+1
],a[
i+1]
−a[i
],a[
i]−a
[i−1
]以及a[i
−1]−
a[i]
a[i-1] - a[i]
a[i−1]
−a[i
]的值,所以我們只需要改變i−1
,i,i
+1
i-1,i,i+1
i−1,i,
i+1的差分值就可以了。
#include
using
namespace std;
#define ll int
#define l(a) t[a].val_to_l
#define r(a) t[a].val_to_r
struct segment_treet[
4000005];
int n,m;
ll a[
1000005];
void
build_tree
(int q,
int l,
int r)
int mid=
(l+r)
>>1;
build_tree
(q*2
,l,mid)
;build_tree
(q*2+1
,mid+
1,r);l
(q)=
l(q*2)
+l(q*2+1
);r(q)=r
(q*2)+
r(q*2+
1);}
void
change_tree
(int q,
int x)
int mid=
(t[q]
.r+t[q]
.l)>>1;
if(x<=mid)
else
l(q)=l
(q*2)+
l(q*2+
1);r
(q)=
r(q*2)
+r(q*2+1
);}ll find_tree
(int p,
int l,
int r,
int op)
int mid=
(t[p]
.l+t[p]
.r)>>1;
if(l<=mid)
if(midreturn ans;
}void
put()}
intmain()
build_tree(1
,1,n);
for(
int i=
1;i<=m;i++
)else
if(x>y)
printf
("%d\n"
,find_tree(1
,y,x-1,
1));
else
printf
("%d\n"
,find_tree(1
,x+1
,y,0))
;}else
// put();
}return0;
}
To Heart 題解 內需消費
題目鏈結 首先,我們先假設這道題不需要修改物價,那麼我們如何找到最好的情況呢?差分。如下數列 1 4 3 5 2很容易觀察出,在第乙個商店到第二個商店中,我們最多可以賺3元,在第乙個商店進貨,第二個商店賣出。但是在第二個商店到第三個商店的途中,我們不能賺錢。因為第二個商店的 比第三個商店的 的 大,...
To Heart 題解 戳西瓜
請不要吝嗇你的點讚!有 n 個西瓜,編號為0 到 n 1,每個西瓜上都標有乙個數字,這些數字存在陣列 nums 中。現在要求你戳破所有的西瓜。每當你戳破乙個西瓜 i 時,你可以獲得 nums left nums i nums right 個硬幣。這裡的 left 和 right 代表和 i 相鄰的兩...
To Heart 題解 收集雪花
題目描述 不同的雪花往往有不同的形狀。在北方的同學想將雪花收集起來,作為禮物送給在南方的同學們。一共有n個時刻,給出每個時刻下落雪花的形狀,用不同的整數表示不同的形狀。在收集的過程中,同學們不希望有重複的雪花。你可以從任意 a時刻開始,在 b時刻停止。a到 b時刻中間的雪花也都將被收集。他們希望收集...