题面
Today, KQ has an exam at the Grail Academy. A strict teacher gave a task that KQ could not solve. He was given two arrays and of length . KQ is allowed to perform the following operations on the arrays:
- Choose an index () and replace with .
- Choose an index () and replace with .
Now he has queries. Each query is described by two numbers and . His task is to find the maximum value of the sum for each query, if he can perform any number of operations on any elements of the array. Since he is not skilled enough for this, he asks for your help.
Input
Each test consists of several test cases. The first line contains one integer () — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers , .
The second line of each test case contains integers .
The third line of each test case contains integers .
The following lines contain two integers and .
It is guaranteed that the sum of the values of and the sum of the values of across all test cases do not exceed .
Output
For each test case, output numbers separated by spaces — the maximum values of the sums .
思路
理清题意,操作有两种类型:
- 选择索引 ,并赋值:
- 选择索引 ,并赋值:
而题目的要求是让KQ进行若干次上述操作,使得对于给出的查询 能够使 最大
可以注意到,对于一个固定位置 ,它修改后的值来源于自己右边或者是 中的同位置元素
因此我们可以定义答案数组 ,并从右往左进行:
对于 ,它右边不可能存在数字,所以
对于 ,要考虑自己右边的情况,所以
所以最终我们所求的那个最大值就是
为了降低时间复杂度,我们使用前缀和进行预处理,将查询的时间复杂度降低到
NOTE为什么要降低时间复杂度?
注意到本题的数据范围很大,而如果对每个查询都循环区间,时间复杂度就是
总的复杂度会变成 ,有很大概率发生
TLE所以我们需要一个时间复杂度更低的方法拿到结果
所以定义前缀和数组 ,有如下:
所以:
代码
#include <bits/stdc++.h>
using namespace std;
int main() { int t; cin >> t; while (t --) { int n, q; cin >> n >> q; vector<int> a(n), b(n); for (int i = 0; i < n; i ++) cin >> a[i]; for (int i = 0; i < n; i ++) cin >> b[i];
vector<long long> F(n), P(n + 1, 0);
F[n - 1] = max(a[n - 1], b[n - 1]); for (int i = n - 2; i >= 0; i --) { F[i] = max((long long)max(a[i], b[i]), F[i + 1]); }
for (int i = 0; i < n; i ++) { P[i + 1] = P[i] + F[i]; }
for (int i = 0; i < q; i ++) { int l, r; cin >> l >> r; l --, r --; cout << P[r + 1] - P[l] << " \n"[i == q - 1]; } }}