感染(high)前綴和+二分+單調棧

題目鏈接

https://nuoyanli.com/contest/1/problem/3D

題面

在這裏插入圖片描述

題意

給定nnai,bia_i,b_iqq次詢問,每次給kk,問至少多少到第幾個ii纔有kmax1m(aibi)k \leq max_1^m(a_i-b_i)。找出這個mm

思路

因爲是求和,所以前綴和處理一下,由於nnqq都在10610^6所以暴力找肯定超時(數據沒給滿導致很多人水過Orz),所以考慮二分,由於變化(aibi)(a_i-b_i)可能爲負數,所以前綴和不具單調性,但是不難發現如果(aibi)0(a_i-b_i )\leq 0這個ii一定不會是答案,因爲1i(aibi)1i1(ai1bi1)\sum_1^i(a_i-b_i)\leq\sum_1^{i-1}(a_{i-1}-b_{i-1})又要天數儘可能小(mm),顯然i1i-1更優,所以我排除這些變化爲負的重新組成一個序列,這個序列具有單調性,所以二分可行。
ps:其實就是維護一個嚴格單調遞增的序列(啓發於單調棧思想)。
注意long long!long\ long!

參考代碼

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
typedef long long LL;
LL a[N], b[N], sum[N];
LL que[N], id[N],n, q,k;
int main() {
	scanf("%d%d",&n,&q);
	for (int i = 1; i <= n; i++) {
		scanf("%lld",&a[i]);
	}

	for (int i = 1; i <= n; i++) {
		scanf("%lld",&b[i]);
	}
	for (int i = 1; i <= n; i++) {
		sum[i] = sum[i - 1] + a[i] - b[i];
	}
	int cnt = 0;
	que[++cnt] = 0;
	id[cnt] = 0;
	for (int i = 1; i <= n; i++) {
		if (sum[i] > que[cnt])
			que[++cnt] = sum[i], id[cnt] = i;
	}
	while (q--) {
		scanf("%lld",&k);
		int pos = lower_bound(que + 1, que + 1 + cnt, k) - que;
		printf("%d\n",id[pos]);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章