蓝桥杯国赛 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]);
		}
	}
}
posted @ 2023-04-24 16:41  兑生  阅读(25)  评论(0编辑  收藏  举报  来源
Live2D