蓝桥杯国赛 123 前缀和 二分
🍑 算法题解专栏
输入
3
1 1
1 3
5 8
输出
1
4
8
🍑 前缀和 嵌套 前缀和
🙈 开 long !!!
import java.io.*;
import java.util.*;
public class Main
{
static int N = 1414215;
// 记录小区间{1}、{1,2}、{1,2…,n}的区间和
// 还记录了小区间的的元素个数 的 前缀和(关键)
static long[] a = new long[N];
static long[] s = new long[N];// 记录小区间的前缀和,
// 求前缀和 1~n
private static long sum(long n)
{
int l = 0;
int r = N;
int mid;
// 二分 找到下标 小于 n 的最后一个区间,满足 a[i] <= i
while (l < r)
{
mid = l + r + 1 >> 1;
if (a[mid] <= n)
l = mid;
else
r = mid - 1;// mid有 -1 ,上边求 mid 就得向上取整
}
// s[l] 为前边所有区间的和 的总和,a[]为当前区间前 k 项的和
// k=(n-s[l]囊括的元素个数[a[l]])
return s[l] + a[(int) (n - a[l])];
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
// 预处理前缀和数组
for (int i = 1; i < N; i++)
{
a[i] = a[i - 1] + i;
s[i] = s[i - 1] + a[i];
}
while (T-- > 0)
{
long l = sc.nextLong();
long r = sc.nextLong();
System.out.println(sum(r) - sum(l - 1));
}
}
}
🍑 纯前缀和:过40%
import java.util.*;
public class Main
{
static int N = (int) 1e7;
static int a[] = new int[N];
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
int idx = 1;
for (int i = 1; i < N; i++)
{
if (idx >= N)
break;
for (int j = 1; j <= i; j++)
{
if (idx >= N)
break;
a[idx++] = j;
}
}
for (int i = 1; i < N; i++)
a[i] += a[i - 1];
while (T-- > 0)
{
int l = sc.nextInt();
int r = sc.nextInt();
System.out.println(a[r] - a[l - 1]);
}
}
}