题目大意:
有两个长度为 n n n的序列 a a a和 b b b, q q q次询问,每次询问一个区间 [ l , r ] [l,r] [l,r],对于区间执行以下操作:
- 选择 l ≤ p o s 1 ≤ p o s 2 ≤ . . . ≤ p o s k ≤ r ( k 为 偶 数 ) l \le pos_1 \le pos_2 \le ... \le pos_k \le r (k为偶数) l≤pos1≤pos2≤...≤posk≤r(k为偶数),对于 a a a序列 p o s 1 , p o s 3 , p o s 5 , . . . pos_1,pos_3,pos_5,... pos1,pos3,pos5,...加1,对于 b b b序列 p o s 2 , p o s 4 , p o s 6 . . . pos_2,pos_4,pos_6... pos2,pos4,pos6...加1,对于每个区间最少多少次使得 ∀ i ∈ [ l , r ] , a i = b i \forall i \in [l,r], a_i = b_i ∀i∈[l,r],ai=bi,每次询问之间独立
解题思路:
- 先把 b b b和 a a a差值求出来,令 d = b − a d=b-a d=b−a
- 一个区间 [ l , r ] [l,r] [l,r]合法的条件就是 d d d从 l l l到 r r r的前缀和均大于等于0,且l到r和为0(注意两者是有不同的)
- 假设 d d d从 l l l到 r r r的前缀和, ∃ i ∈ [ l , r ] \exist i \in [l, r] ∃i∈[l,r], 使得前缀和小于0,因为对于 d d d数组,每次都要先对大于0的减1,对小于0的加1,又因为操作位置是递增的,如果出现有前缀和小于0,则说明当前 i i i位置不管怎么利用前面大于0的d数组都无法变成0
- 所以贪心最终答案就是 [ l , r ] [l,r] [l,r]前缀和的最大值
- 那题目还有要求每次操作序列长度是偶数,其实加上这个条件就是相当于把这题变成类似最深的括号匹配深度,所以贪心是对的
AC代码:
#include <bits/stdc++.h>
#define ft first
#define sd second
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0) //不能跟puts混用
#define seteps(N) fixed << setprecision(N)
#define endl "\n"
const int maxn = 1e5 + 10;
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const ll mod = 1e9 + 7;
int n, q;
ll a[maxn], b[maxn], d[maxn], sum[maxn];
ll m1[20][maxn], m2[20][maxn];
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
for (int i = 1; i <= n; i++) d[i] = b[i] - a[i], sum[i] = sum[i - 1] + d[i], m1[0][i] = m2[0][i] = sum[i];
for (int j = 1; j <= 18; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
m1[j][i] = min(m1[j - 1][i], m1[j - 1][i + (1 << (j - 1))]);
m2[j][i] = max(m2[j - 1][i], m2[j - 1][i + (1 << (j - 1))]);
}
}
int l, r;
while (q--) {
cin >> l >> r;
if (sum[r] - sum[l - 1]) {
puts("-1");
continue;
}
int j = 31 - __builtin_clz(r - l + 1);
ll mn = min(m1[j][l], m1[j][r - (1 << j) + 1]);
ll mx = max(m2[j][l], m2[j][r - (1 << j) + 1]);
if (mn - sum[l - 1] < 0) puts("-1");
else cout << mx - sum[l - 1] << endl;
}
return 0;
}