描述
給定乙個陣列a[1..n],你需要選乙個盡可能長的非空連續子段,使得這個子段的和小於等於給定的乙個數 s.
輸入 第一行兩個整數 n,s
第二行 n 個整數,第 i 個整數表示 a[i]
對於 30% 的資料,有1 ≤ n ≤ 103
對於 100% 的資料,有1 ≤ n ≤ 2×105,-109 ≤ a[i] ≤ 109
輸出 輸出滿足題目條件的最長的連續子段的長度,如果不存在這樣的連續子段,輸出 -1。
樣例輸入思路:3 -1
4 -3 2
樣例輸出
2
連續的子段和可以利用字首和算出來,最暴力的接髮就是列舉每個子段的和看是否小於等於s,這樣的時間複雜度是o(
n2) o(n
2)
,肯定過不了,肯定有個優化,考慮o(
nlog
n)o (n
logn
)的解法,直覺上可以用二分可以將時間複雜度優化到o(
nlog
n)o (n
logn
), 由於二分的前提條件是序列要有序的,怎麼去構造這個有序的序列b呢?我們令b[
i]b [i
]表示前i個數中所有字首和加上s的最大值。即 b[
i]=m
ax(s
um[i
]+s,
b[i−
1]) b[i
]=ma
x(su
m[i]
+s,b
[i−1
])
這樣保證了b陣列是有序的。然後在b陣列中找第乙個大於sum[i]的值的下標。比如要求子段[i,j]和,那麼就是 su
m[j]
−sum
[i−1
]≤s sum
[j]−
sum[
i−1]
≤s
即 su
m[j]
+s≥s
um[i
] sum
[j]+
s≥su
m[i]
這不等式的左邊就是b陣列中存的數。
#include
#include
#include
using
namespace
std;
const
int maxn = 1e5+5;
long
long a[maxn*2];
long
long b[maxn*2];
long
long sum[maxn*2];
int main()
b[0] = s;
for (int i = 1; i <= n; ++i)
b[i] = max(sum[i]+s,b[i-1]);
int res = -1;
for (int i = n; i >= 1; --i)
cout
<< res << endl;
return
0;}
每日一題之 hiho1744 hohahola
描述 有一種叫作hohahola的飲料,售價是x元一瓶。小hi非常喜歡這種飲料,但是他現在身無分文。不過小hi有n張優惠券,買hohahola時每瓶最多使用一張優惠券,可以使該瓶 減少y元。y x 同時優惠券可以 小hi每 一張優惠券可以獲得z元。請你幫小hi計算通過 若干優惠券,他最多可以買多少瓶...
每日一題之 hiho1304 24點
週末,小hi和小ho都在家待著。在收拾完房間時,小ho偶然發現了一副撲克,於是兩人考慮用這副撲克來打發時間。小ho 玩點什麼好呢?小hi 兩個人啊,不如來玩24點怎麼樣,不靠運氣就靠實力的遊戲。小ho 好啊,好啊。經過若干局遊戲之後 小ho 小hi,你說如果要寫個程式來玩24點會不會很複雜啊?小hi...
每日一題之 hiho197 逆序單詞
描述 在英文中有很多逆序的單詞,比如dog和god,evil和live等等。現在給出乙份包含n個單詞的單詞表,其中每個單詞只出現一次,請你找出其中有多少對逆序單詞。輸入 第1行 1個整數,n,表示單詞數量。2 n 50,000。第2.n 1行 每行1個單詞,只包含小寫字母,每個單詞長度不超過16個字...