2023-09-01:用go语言编写。给出两个长度均为n的数组,

A = { a1, a2, ... ,an },

B = { b1, b2, ... ,bn }。

你需要求出其有多少个区间[L,R]满足:

数组A中下标在[L,R]中的元素之和在[La,Ra]之中,

数组B中下标在[L,R]中的元素之和在[Lb,Rb]之中。

输入:

第一行有一个正整数N(1<=N<=100000),代表两个数组的长度。

第二行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。

第三行有N个非负整数,范围在0到1000000000之间,代表数组中的元素。

第四行有4个整数La,Ra,Lb,Rb,范围在0到10^18之间,代表题目描述中的参数。

输出:

输出一个整数,代表所求的答案。

来自微众银行。

来自左程云

答案2023-09-01:

大体过程如下:

1.定义两个暴力方法(nums1和nums2)来求解问题。这两个方法的输入参数包括两个数组A和B,数组A的左右边界(la和ra),数组B的左右边界(lb和rb)。

2.方法nums1使用暴力的方法遍历所有可能的区间,并统计满足条件的区间个数。

  • 初始化变量ans为0,表示满足条件的区间个数。

  • 使用两层循环遍历数组A的所有可能区间。外层循环变量l表示区间的左边界,内层循环变量r表示区间的右边界。

  • 对于每个区间,初始化变量sumA和sumB为0,分别表示数组A和数组B中元素之和。

  • 使用一个循环遍历当前区间内的元素,累加sumA和sumB。

  • 判断sumA是否在[la, ra]之间,sumB是否在[lb, rb]之间,如果满足条件则增加ans的值。

  • 返回ans作为结果。

3.方法nums2使用优化的方法来求解问题。

  • 初始化变量ans为0,表示满足条件的区间个数。

  • 初始化变量rightA1、sumA1、rightA2、sumA2、rightB1、sumB1、rightB2、sumB2为0,分别表示数组A和数组B的右边界和元素之和。

  • 使用一个循环遍历数组A的所有可能左边界。循环变量l表示左边界的位置。

  • 在循环中,使用while循环更新rightA1、sumA1、rightA2、sumA2、rightB1、sumB1、rightB2、sumB2,使其满足条件。

  • 计算数组A和数组B的左右交集的左边界left和右边界right。

  • 如果left小于right,则将right减去left的值加到ans中。

  • 根据当前左边界l更新rightA1、sumA1、rightA2、sumA2、rightB1、sumB1、rightB2、sumB2。

  • 返回ans作为结果。

4.定义randomArray方法,用于生成指定长度和范围的随机数组。

  • 输入参数包括数组的长度n和随机数的范围v。

  • 初始化一个长度为n的数组ans。

  • 使用一个循环遍历数组,为每个元素赋一个随机数值。

  • 返回生成的随机数组ans。

5.定义max和min方法,分别用于求两个数的最大值和最小值。

6.在main函数中进行测试。

  • 初始化随机数种子。

  • 定义常量N和V,表示数组的长度和随机数的范围。

  • 定义变量testTimes,表示测试次数。

  • 使用循环进行测试。

  • 在每次测试中,生成随机数组A和B,以及随机的la、ra、lb、rb。

  • 调用nums1和nums2方法,分别得到暴力和优化方法的结果。

  • 比较两个结果,如果不一致则输出错误信息。

  • 完成测试后输出测试结束信息。

总的时间复杂度:

  • 对于方法nums1,需要三重循环遍历数组,时间复杂度为O(n^3)。

  • 对于方法nums2,需要两重循环遍历数组,时间复杂度为O(n^2)。

总的额外空间复杂度:

  • 除了输入参数外,额外使用的空间主要是变量和随机数组。因此,额外空间复杂度为O(n)。

go完整代码如下:

package main

import (
"math/rand"
"fmt"
"time"
) // 暴力方法
func nums1(A []int, B []int, la int, ra int, lb int, rb int) int {
n := len(A)
ans := 0
for l := 0; l < n; l++ {
for r := l; r < n; r++ {
sumA := 0
sumB := 0
for i := l; i <= r; i++ {
sumA += A[i]
sumB += B[i]
}
if sumA >= la && sumA <= ra && sumB >= lb && sumB <= rb {
ans++
}
}
}
return ans
} // 正式方法
func nums2(A []int, B []int, la int, ra int, lb int, rb int) int {
n := len(A)
ans := 0
rightA1, sumA1, rightA2, sumA2 := 0, 0, 0, 0
rightB1, sumB1, rightB2, sumB2 := 0, 0, 0, 0
for l := 0; l < n; l++ {
for rightA1 < n && sumA1+A[rightA1] < la {
sumA1 += A[rightA1]
rightA1++
}
for rightA2 < n && sumA2+A[rightA2] <= ra {
sumA2 += A[rightA2]
rightA2++
}
for rightB1 < n && sumB1+B[rightB1] < lb {
sumB1 += B[rightB1]
rightB1++
}
for rightB2 < n && sumB2+B[rightB2] <= rb {
sumB2 += B[rightB2]
rightB2++
}
left := max(rightA1, rightB1)
right := min(rightA2, rightB2)
if left < right {
ans += right - left
}
if rightA1 == l {
rightA1++
} else {
sumA1 -= A[l]
}
sumA2 -= A[l]
if rightB1 == l {
rightB1++
} else {
sumB1 -= B[l]
}
sumB2 -= B[l]
}
return ans
} func randomArray(n int, v int) []int {
ans := make([]int, n)
for i := 0; i < n; i++ {
ans[i] = rand.Intn(v)
}
return ans
} func max(a int, b int) int {
if a > b {
return a
}
return b
} func min(a int, b int) int {
if a < b {
return a
}
return b
} func main() {
rand.Seed(time.Now().Unix())
N := 50
V := 100
testTimes := 10000
fmt.Println("测试开始")
for i := 0; i < testTimes; i++ {
n := rand.Intn(N)
A := randomArray(n, V)
B := randomArray(n, V)
a := rand.Intn(V)
b := rand.Intn(V)
c := rand.Intn(V)
d := rand.Intn(V)
la := min(a, b)
ra := max(a, b)
lb := min(c, d)
rb := max(c, d)
ans1 := nums1(A, B, la, ra, lb, rb)
ans2 := nums2(A, B, la, ra, lb, rb)
if ans1 != ans2 {
fmt.Println("出错了!")
}
}
fmt.Println("测试结束")
}

rust完整代码如下:

use rand::Rng;

fn nums1(A: &[i32], B: &[i32], la: i32, ra: i32, lb: i32, rb: i32) -> i32 {
let n = A.len();
let mut ans = 0;
for l in 0..n {
for r in l..n {
let mut sum_a = 0;
let mut sum_b = 0;
for i in l..=r {
sum_a += A[i];
sum_b += B[i];
}
if sum_a >= la && sum_a <= ra && sum_b >= lb && sum_b <= rb {
ans += 1;
}
}
}
ans
} fn nums2(A: &[i32], B: &[i32], la: i32, ra: i32, lb: i32, rb: i32) -> i32 {
let n = A.len() as i32;
let mut ans = 0;
let (mut right_a1, mut sum_a1, mut right_a2, mut sum_a2) = (0, 0, 0, 0);
let (mut right_b1, mut sum_b1, mut right_b2, mut sum_b2) = (0, 0, 0, 0);
for l in 0..n {
while right_a1 < n && sum_a1 + A[right_a1 as usize] < la {
sum_a1 += A[right_a1 as usize];
right_a1 += 1;
}
while right_a2 < n && sum_a2 + A[right_a2 as usize] <= ra {
sum_a2 += A[right_a2 as usize];
right_a2 += 1;
}
while right_b1 < n && sum_b1 + B[right_b1 as usize] < lb {
sum_b1 += B[right_b1 as usize];
right_b1 += 1;
}
while right_b2 < n && sum_b2 + B[right_b2 as usize] <= rb {
sum_b2 += B[right_b2 as usize];
right_b2 += 1;
}
let left = right_a1.max(right_b1);
let right = right_a2.min(right_b2);
if left < right {
ans += right - left;
}
if right_a1 == l {
right_a1 += 1;
} else {
sum_a1 -= A[l as usize];
}
sum_a2 -= A[l as usize];
if right_b1 == l {
right_b1 += 1;
} else {
sum_b1 -= B[l as usize];
}
sum_b2 -= B[l as usize];
}
ans
} fn random_array(n: i32, v: i32) -> Vec<i32> {
let mut rng = rand::thread_rng();
(0..n).map(|_| rng.gen_range(0, v)).collect()
} fn main() {
const N: i32 = 50;
const V: i32 = 100;
const TEST_TIMES: usize = 10000;
println!("测试开始");
for _ in 0..TEST_TIMES {
let n = rand::thread_rng().gen_range(0, N);
let A = random_array(n, V);
let B = random_array(n, V);
let a = rand::thread_rng().gen_range(0, V);
let b = rand::thread_rng().gen_range(0, V);
let c = rand::thread_rng().gen_range(0, V);
let d = rand::thread_rng().gen_range(0, V);
let la = a.min(b);
let ra = a.max(b);
let lb = c.min(d);
let rb = c.max(d);
let ans1 = nums1(&A, &B, la, ra, lb, rb);
let ans2 = nums2(&A, &B, la, ra, lb, rb);
if ans1 != ans2 {
println!("出错了!");
}
}
println!("测试结束");
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <cstdlib> using namespace std; int nums1(vector<int>& A, vector<int>& B, int la, int ra, int lb, int rb) {
int n = A.size();
int ans = 0;
for (int l = 0; l < n; l++) {
for (int r = l; r < n; r++) {
int sumA = 0;
int sumB = 0;
for (int i = l; i <= r; i++) {
sumA += A[i];
sumB += B[i];
}
if (sumA >= la && sumA <= ra && sumB >= lb && sumB <= rb) {
ans++;
}
}
}
return ans;
} int nums2(vector<int>& A, vector<int>& B, int la, int ra, int lb, int rb) {
int n = A.size();
int ans = 0;
int rightA1 = 0, sumA1 = 0, rightA2 = 0, sumA2 = 0, rightB1 = 0, sumB1 = 0, rightB2 = 0, sumB2 = 0;
for (int l = 0; l < n; l++) {
while (rightA1 < n && sumA1 + A[rightA1] < la) {
sumA1 += A[rightA1++];
}
while (rightA2 < n && sumA2 + A[rightA2] <= ra) {
sumA2 += A[rightA2++];
}
while (rightB1 < n && sumB1 + B[rightB1] < lb) {
sumB1 += B[rightB1++];
}
while (rightB2 < n && sumB2 + B[rightB2] <= rb) {
sumB2 += B[rightB2++];
}
int left = max(rightA1, rightB1);
int right = min(rightA2, rightB2);
if (left < right) {
ans += right - left;
}
if (rightA1 == l) {
rightA1++;
}
else {
sumA1 -= A[l];
}
sumA2 -= A[l];
if (rightB1 == l) {
rightB1++;
}
else {
sumB1 -= B[l];
}
sumB2 -= B[l];
}
return ans;
} vector<int> randomArray(int n, int v) {
vector<int> ans(n);
for (int i = 0; i < n; i++) {
ans[i] = rand() % v;
}
return ans;
} int main() {
int N = 50;
int V = 100;
int testTimes = 10000;
cout << "测试开始" << endl;
for (int i = 0; i < testTimes; i++) {
int n = rand() % N;
vector<int> A = randomArray(n, V);
vector<int> B = randomArray(n, V);
int a = rand() % V;
int b = rand() % V;
int c = rand() % V;
int d = rand() % V;
int la = min(a, b);
int ra = max(a, b);
int lb = min(c, d);
int rb = max(c, d);
int ans1 = nums1(A, B, la, ra, lb, rb);
int ans2 = nums2(A, B, la, ra, lb, rb);
if (ans1 != ans2) {
cout << "出错了!" << endl;
}
}
cout << "测试结束" << endl; return 0;
}

c完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h> // 暴力方法
// 为了测试
int nums1(int* A, int* B, int n, int la, int ra, int lb, int rb) {
int ans = 0;
for (int l = 0; l < n; l++) {
for (int r = l; r < n; r++) {
int sumA = 0;
int sumB = 0;
for (int i = l; i <= r; i++) {
sumA += A[i];
sumB += B[i];
}
if (sumA >= la && sumA <= ra && sumB >= lb && sumB <= rb) {
ans++;
}
}
}
return ans;
} // 正式方法
// 时间复杂度O(N)
int nums2(int* A, int* B, int n, int la, int ra, int lb, int rb) {
int ans = 0;
int rightA1 = 0, sumA1 = 0, rightA2 = 0, sumA2 = 0, rightB1 = 0, sumB1 = 0, rightB2 = 0, sumB2 = 0;
for (int l = 0; l < n; l++) {
while (rightA1 < n && sumA1 + A[rightA1] < la) {
sumA1 += A[rightA1++];
}
while (rightA2 < n && sumA2 + A[rightA2] <= ra) {
sumA2 += A[rightA2++];
}
while (rightB1 < n && sumB1 + B[rightB1] < lb) {
sumB1 += B[rightB1++];
}
while (rightB2 < n&& sumB2 + B[rightB2] <= rb) {
sumB2 += B[rightB2++];
}
int left = rightA1 > rightB1 ? rightA1 : rightB1;
int right = rightA2 < rightB2 ? rightA2 : rightB2;
if (left < right) {
ans += right - left;
}
if (rightA1 == l) {
rightA1++;
}
else {
sumA1 -= A[l];
}
sumA2 -= A[l];
if (rightB1 == l) {
rightB1++;
}
else {
sumB1 -= B[l];
}
sumB2 -= B[l];
}
return ans;
} // 为了测试
int* randomArray(int n, int v) {
int* ans = (int*)malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
ans[i] = rand() % v;
}
return ans;
} // 为了测试
int main() {
int N = 50;
int V = 100;
int testTimes = 10000;
printf("测试开始\n");
srand(time(NULL));
for (int i = 0; i < testTimes; i++) {
int n = rand() % N;
int* A = randomArray(n, V);
int* B = randomArray(n, V);
int a = rand() % V;
int b = rand() % V;
int c = rand() % V;
int d = rand() % V;
int la = (a < b) ? a : b;
int ra = (a > b) ? a : b;
int lb = (c < d) ? c : d;
int rb = (c > d) ? c : d;
int ans1 = nums1(A, B, n, la, ra, lb, rb);
int ans2 = nums2(A, B, n, la, ra, lb, rb);
if (ans1 != ans2) {
printf("出错了!\n");
}
free(A);
free(B);
}
printf("测试结束\n");
return 0;
}

2023-09-01:用go语言编写。给出两个长度均为n的数组, A = { a1, a2, ... ,an }, B = { b1, b2, ... ,bn }。 你需要求出其有多少个区间[L,R]的更多相关文章

  1. UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

    题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A< ...

  2. 主席树——求区间[l,r]不同数字个数的模板(向左密集 D-query)

    主席树的另一种用途,,(还有一种是求区间第k大,区间<=k的个数) 事实上:每个版本的主席树维护了每个值最后出现的位置 这种主席树不是以权值线段树为基础,而是以普通的线段树为下标的 /* 无修改 ...

  3. luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值

    ————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...

  4. 查询数组里有多少个数在[L,R]范围中(二分)

    使用两次二分即可得到这个值 比如现在有一个vector<int> vec,里面存放的是有序数列. 我们现在希望找出范围在[L,R]之间的数有多少个. 则有cnt = upper_bound ...

  5. D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

    D. Powerful array time limit per test seconds memory limit per test megabytes input standard input o ...

  6. hdu 4630 查询[L,R]区间内任意两个数的最大公约数

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. HDU 6356 (线段树-l,r 之间小于val 的变val+单点求值)

    题目描述: 给你一个长度为n的最开始为0的数以及m个更新操作以及数据生成器参数X,Y,Z.每次操作,将由数据生成器生成出li,ri,vi.让你从区间[li,ri]中,将所有小于vi的数变为vi.最后让 ...

  8. 在一个由 'L' , 'R' 和 'X' 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。一次移动操作指用一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。现给定起始字符串start和结束字符串end,请编写代码,当且仅当存在一系列移动操作使得start可以转换成end时, 返回True。

    在一个由 'L' , 'R' 和 'X' 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作.一次移动操作指用一个"LX"替换一个"XL ...

  9. 2017-5-14 湘潭市赛 Partial Sum 给n个数,每次操作选择一个L,一个R,表示区间左右端点,该操作产生的贡献为[L+1,R]的和的绝对值-C。 0<=L<R<=n; 如果选过L,R这两个位置,那么以后选择的L,R都不可以再选择这两个位置。最多操作m次,求可以获得的 最大贡献和。

    Partial Sum Accepted : Submit : Time Limit : MS Memory Limit : KB Partial Sum Bobo has a integer seq ...

  10. Help Hanzo lightof 1197 求一段区间内素数个数,[l,r] 在 [1,1e9] 范围内。r-l<=1e5; 采用和平常筛素数的方法。平移区间即可。

    /** 题目:Help Hanzo lightof 1197 链接:https://vjudge.net/contest/154246#problem/M 题意:求一段区间内素数个数,[l,r] 在 ...

随机推荐

  1. < Python全景系列-3 > Python控制流程盘点及高级用法、神秘技巧大揭秘!

    欢迎来到我们的系列博客<Python全景系列>!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题,帮助你掌握这门强大而灵活的编程语法.无论你是编程新手,还是有一 ...

  2. 三款Github Copilot的免费替代

    大家好我是费老师,提起Github Copilot,相信很多读者朋友们都听说过甚至使用过,作为Github研发的一款先进的编程辅助插件,它可以在我们日常编写代码的过程中,根据代码的上下文内容.注释等信 ...

  3. flutter填坑之旅(有状态组件StatefulWidget)

    今天我们来看看flutter的StatefulWidget(有状态组件),最常用就是app 主页的底部导航栏的应用 效果图 首页 关于 我的 statefull-widget-learn .dart ...

  4. 2023-05-25:给定一个正整数 x,我们将会写出一个形如 x (op1) x (op2) x (op3) x ... 的表达式 其中每个运算符 op1,op2,… 可以是加、减、乘、除之一 例如

    2023-05-25:给定一个正整数 x,我们将会写出一个形如 x (op1) x (op2) x (op3) x ... 的表达式 其中每个运算符 op1,op2,- 可以是加.减.乘.除之一 例如 ...

  5. ODOO13之六:Odoo 13开发之模型 – 结构化应用数据

    在本系列文章第三篇Odoo 13 开发之创建第一个 Odoo 应用中,我们概览了创建 Odoo 应用所需的所有组件.本文及接下来的一篇我们将深入到组成应用的每一层:模型层.视图层和业务逻辑层. 本文中 ...

  6. WPF 入门笔记 - 03 - 样式基础及控件模板

    原学习路线是按照圣殿骑士的<WPF基础到企业应用系列>的路线走的,但是布局之后直接依赖属性学起来有些僵硬,不太好理解,尝试了文章的前部分内容后放弃,调整为本篇博文内容.笔记路线将按照痕迹g ...

  7. JAVA 使用IText7 + Freemarker 动态数据生成PDF实现案例

    技术方案:IText7 + Freemarker 技术文档 Itext 官网:https://itextpdf.com/ itext API文档:https://api.itextpdf.com/iT ...

  8. 基于ggplot2的解剖图和组织模块可视化

    摘要 将数据显示到解剖结构上,是一种可以快速观察组织相关信息的便捷技术.然而,绘制组织是一项复杂的任务(a complex task),需要解剖学和艺术方面的专业知识.虽然已经存在可用于在解剖图上显示 ...

  9. Java中读取用户输入的是谁?Scanner类

    前言 我们在初学 Java 编程的时候,总是感觉很枯燥乏味,想着做点可以交互的小系统,可以让用户自由输入,系统可以接收做出反映.这就要介绍一下 Java 中的 Scanner 类了. 一.Scanne ...

  10. 自然语言处理 Paddle NLP - 基于预训练模型完成实体关系抽取

    自然语言处理 Paddle NLP - 信息抽取技术及应用 重点:SOP 图.BCEWithLogitsLoss 基于预训练模型完成实体关系抽取 信息抽取旨在从非结构化自然语言文本中提取结构化知识,如 ...