首页 > 其他分享 >【二分+前缀和+后缀和】codeforces 2026 D. Sums of Segments

【二分+前缀和+后缀和】codeforces 2026 D. Sums of Segments

时间:2024-11-28 21:59:51浏览次数:5  
标签:... ll loc Segments 元素 Sums codeforces leq sum

题目

https://codeforces.com/problemset/problem/2026/D

题意

第一行输入一个正整数 \(n(1 \leq n \leq 3e5)\),第二行输入 \(n\) 个整数 \(a_1, a_2, ..., a_i, ..., a_n(-10 \leq a_i \leq 10)\),第三行输入一个正整数 \(q(1 \leq q \leq 3e5)\),随后 \(q\) 行,每行输入两个整数 \(l_i, r_i(1 \leq l_i \leq r_i \leq \frac{n(n+1)}{2})\)。

对于数组 \(a\),我们会得到一个数组 \(b = [a_1, a_1 + a_2, ..., a_1 + a_2 + ... + a_n, a_2, a_2 + a_3, ..., a_2 + a_3 + ... + a_n, ..., a_n]\) 共 \(\frac{n(n + 1)}{2}\) 个元素,对于每个询问要求的是 \(\sum_{j = l_i}^{r_i}{b_j}\)。

题解

对于数组 \(a = [a_1, a_2, ..., a_i, ..., a_n]\),由于 \(1 \leq n \leq 3e5\),那么 \(b\) 元素个数会达到 \(1 \leq \frac{n(n+1)}{2} \leq 45000000000\) 的量级,因此不能直接求出 \(b\) 的每一个元素。不妨对数组 \(b\) 分为 \(n\) 组:

第一组

\(a_1, a_1 + a_2, ..., a1_ + a_2 + ... + a_n\)

第二组

\(a_2, a_2 + a_3, ..., a_2 + a_3 + ... + a_n\)

...

第 \(n\) 组

\(a_n\)

易知从第一组到第 \(n\) 组的元素个数分别是 \(n, n - 1, ..., 1\),若只是求出其中一组,时间复杂度为 \(O(n)\) 是可以接受的。

观察可以发现:第二组可以由第一组每个元素都删去一个 \(a_1\) 得到;第三组可以由第二组每个元素都删去一个 \(a_2\) 得到;以此类推。于是可以先计算出\(sum_1(a_1 + a_2 + ... + a_n)\),\(sum_2(a_2 + ... + a_n)\), ..., \(sum_n(a_n)\)。

假设我想计算 \(b\) 第 \(1 ~ x\) 项的和,那么需要计算出第 \(x\) 项位于第几个 \(sum\),计算方式可以使用二分法。不妨视为第 \(i\) 个,然后计算 \(sum_i\) 需要删掉的元素个数 \(cnt\)。此时问题就转化为如何计算出需要删掉的元素的和,或者是如何计算出最后一组不包括被删除元素的元素之和?

不妨假设 \(n = 4,x = 2\),那么此时 \(cnt = 2,sum_1 = a_1 + (a_1 + a_2) + (a_1 + a_2 + a_3) + (a_1 + a_2 + a_3 + a_4),\sum_{j=1}^{2}{b_j} = a_1 + (a_1 + a_2)\),可得 \(\sum_{j=1}^{2}{b_j} = sum_1 - (a_1 + a_2 + a_3) - (a_1 + a_2 + a_3 + a_4)\)。

删除的元素可以视为 \((a_1 + a_2 + a_3) + (a_1 + a_2 + a_3 + a_4) = 2 \times (a_1 + a_2) + a_3 + (a_3 + a_4) = cnt \times (a_1 + a_2) + a_3 + (a_3 + a_4)\)。观察分好组的数据,易知 \(a_3 + (a_3 + a_4)\) 刚好是倒数第 \(cnt\) 组。由归纳法,可以得出结论:
\(sum_i - sum_cnt - cnt \times 剩余的数最大值\) 就是最后一个 \(sum_i\) 剩余的值。至于前面的 \(sum_1~sum_i-1\) 直接使用前缀和维护即可。

参考代码

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std;
using ll = long long;

constexpr int N = 3e5 + 7;
int n, q;
ll l, r;
ll a[N];
ll b[N];//第 i 组元素的总和
ll c[N];//维护第 1~i 组的总元素个数,分别是 n, n + (n - 1), n + (n - 1) + (n - 2), ...
ll apre[N];//a的前缀和
ll apst[N];//a的后缀和
ll bpre[N];//b的前缀和

ll calc(ll x) {//计算出从 b1~bx 的和
	int loc = lower_bound(c + 1, c + 1 + n, x) - c;//计算出第 x 项所在组 loc
	ll res = bpre[loc];
	if (c[loc] > x) {
		res = bpre[loc - 1];
		int deleteNum = c[loc] - x;//需要删掉的数的数量 
		ll lastNum = apst[loc] - apst[n - deleteNum + 1];//删掉 deleteNum 个数后剩余最大元素
		res += b[loc] - b[n - deleteNum + 1] - lastNum * deleteNum;//第 loc 组的和减去 倒数第 deleteNum 组的和并减去 deletNum 个剩余最大元素
	}
	return res;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; ++ i) {
		cin >> a[i];
		apre[i] += apre[i - 1] + a[i];//求数组 a 的前缀和
	}
	for (int i = n; i >= 1; -- i) {
		apst[i] = apst[i + 1] + a[i];//求数组 b 的前缀和
		b[i] = apre[i] + b[i + 1];//数组 a 的前缀和的前缀和,也就是第 i 组的和
	}
	c[1] = n;//第一组的元素个数
	for (int i = 2; i <= n; ++ i) {
		c[i] = c[i - 1] + (n - i + 1);//第一组到第 i 组的总元素个数
		b[i] = b[i - 1] - a[i - 1] * (n - i + 2);//第 i 组的元素之和
	}
	for (int i = 1; i <= n; ++ i) bpre[i] = b[i] + bpre[i - 1];//数组 b 前缀和的前缀和,也就是第一组到第 i 组的总元素之和
	cin >> q;
	while (q --) {
		cin >> l >> r;
		cout << calc(r) - calc(l - 1) << '\n';
	}
	return 0;
}

标签:...,ll,loc,Segments,元素,Sums,codeforces,leq,sum
From: https://www.cnblogs.com/RomanLin/p/18574549

相关文章

  • 每日一题:https://codeforces.com/contest/1999/problem/D
    题目链接:https://codeforces.com/contest/1999/problem/D#include<iostream>#include<string>#include<vector>usingnamespacestd;intmain(){intn;cin>>n;for(;n>0;n--){stringarr1;stringarr2;......
  • Codeforces 赛题整合1
    对于训练赛的赛题整合。文章目录2033D-Kousuke'sAssignment题意:题解:代码2033C-Sakurako'sFieldTrip题意题解代码2022B-KarSalesman题意题解代码2025C-NewGame题意题解代码2033D-Kousuke’sAssignmentcodeforces链接题意:找出数组中最多有多少......
  • Codeforces 333 题目研讨
    题目传送门:ABCDEA解法:注意到最终支付的一定是\(3^k\)的钱。即得。B解法:不难发现芯片的前进路上不能有障碍,否则不可能在\(n-1\)步内完成。然后又不难发现,同一行或一列只能放一个。双不难发现,当\(n\)为奇数时,中行或中列可能会冲突,此时需要移除其中一个。叒不难发现,当......
  • Codeforces Round 986 (Div. 2) A-C
    A.Alice'sAdventuresin"Chess"AliceistryingtomeetupwiththeRedQueeninthecountryside!Rightnow,Aliceisatposition\((0,0)\),andtheRedQueenisatposition\((a,b)\).Alicecanonlymoveinthefourcardinaldirecti......
  • 【异或运算】codeforces 1153 B. Dima and a Bad XOR
    前言异或运算:是一种在二进制数系统中使用的逻辑运算。它的基本规则是对两个二进制位进行比较,如果这两个位不同,则结果为\(1\);如果相同,则结果为\(0\)。异或运算的规则\(0\)XOR\(0\)=\(0\)\(0\)XOR\(1\)=\(1\)\(1\)XOR\(0\)=\(1\)\(1\)XOR\(1\)=\(0\)特性......
  • CF1389F Bicolored Segments
    CF1389FBicoloredSegments题目大意:给你\(n\)条线段\([l_1,r_1],[l_2,r_2],\ldots,[l_n,r_n]\)。线段有两种颜色,第\(i\)条线段的颜色为\(t_i\)。我们称一对线段\(i,j\)是不好的,当且仅当以下两个条件同时满足:\(t_i\neqt_j\);线段\([l_i,r_i]\)和\([l_j,......
  • [CodeForces] CF21 题解
    这次不放难度了。因为我懒A.JabberID【题目大意】一个地址由<username>@<hostname>[/resource]组成,其中[/resource]可以被省略。<username>字段允许大写、小写字母,数字、下划线,其长度应在\(1\)到\(16\)之间。<hostname>字段允许用.来分隔。每一段的要求同<u......
  • 【CodeForces训练记录】CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)
    训练情况赛后反思发现自己越来越能猜结论了,连续两题结论猜对了,一把rating上青了。A题构造一个数组使得模数互不相同,考虑构造一个模数为\([0,1,2,3,4,5]\)的数列,所以一个全是奇数的数列\([1,3,5,7,9]\)符合条件,直接输出\(1\simn\)的奇数即可。#include<bits/stdc++.......
  • 每日一题:https://codeforces.com/contest/2005/problem/B1
    题目链接:https://codeforces.com/contest/2005/problem/B1(开局看掉m=2和q=1)includeincludeusingnamespacestd;intmain(){longu;cin>>u;for(;u>0;u--){longn;longm,q;longarr1[3];longcha;cin>>n>>m>>q;for(inti=0;i<2;i++){......
  • Codeforces Round 979 (Div. 2) B. Minimise Oneness
    题目链接:题目大意:构造长度为nnn的01字符串,使得全为零的子序列和至少有一个1的子序列的数量之差的绝对值最小。思路:很明显,所有子序列中不是全为0就是至少有一个1,所以算......