首页 > 其他分享 >[题解]CF1748C Zero-Sum Prefixes

[题解]CF1748C Zero-Sum Prefixes

时间:2023-10-03 13:45:05浏览次数:51  
标签:前缀 re int 题解 Prefixes vis Zero Max sim

UPD 23.10.3 更新的对思路的描述,以及代码。

思路

对于每一个 \(a_i = 0\),如果我们将它变为 \(x\),都可以直接将 \(i \sim n\) 位置上的前缀和加 \(x\)。

设 \(a_j\) 是 \(a_i\) 后第一个 \(0\),那么,在 \(j\) 时同样有上述规律。

所以,我们只需在 \(i\) 时考虑,\(i \sim (j - 1)\) 的贡献。

因为我们想尽可能的使 \(s_x = 0\) 的数量更多,所以我们就要让 \(a_i\) 修改为在 \(i \sim (j - 1)\) 中 \(s_k\) 出现次数最多的元素的相反数。

特别的,如果 \(i\) 后没有任意一个位置 \(j\) 为 \(0\),那么,考虑 \(i \sim n\) 即可。(直接加一个 \(n + 1\) 的哨兵即可)

因为 \(i\) 的修改对 \(1 \sim (i - 1)\) 的前缀和无关,所以只需枚举 \(i \sim (j - 1)\) 的位置,保证了更新的位置总和是 \(\Theta(n)\),然后还需要用一个 map 维护前缀和的出现次数。

综上,时间复杂度为 \(\Theta(n \log n)\)。

code

#include <bits/stdc++.h>
#define re register
#define ll long long

using namespace std;

const int N = 2e5 + 10;
int T,n;
int arr[N];
ll s[N];

inline int read(){
	int r = 0,w = 1;
	char c = getchar();
	while (c < '0' || c > '9'){
		if (c == '-') w = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9'){
		r = (r << 1) + (r << 3) + (c ^ 48);
		c = getchar();
	}
	return r * w;
}

int main(){
	T = read();
	while (T--){
		int ans = 0,len = 0;
		vector<int> v;
		n = read();
		for (re int i = 1;i <= n;i++) arr[i] = s[i] = 0;
		for (re int i = 1;i <= n;i++){
			arr[i] = read();
			s[i] = s[i - 1] + arr[i];
			if (!arr[i]){
				len++;
				v.push_back(i);
			}
		}
		v.push_back(n + 1);
		for (re int i = 1;i < v.front();i++){
			if (!s[i]) ans++;
		}
		for (re int x = 0;x < len;x++){
			unordered_map<ll,int> vis;
			int Max = 0;
			for (re int i = v[x];i < v[x + 1];i++){
				vis[s[i]]++;
				Max = max(Max,vis[s[i]]);
			}
			ans += Max;
		}
		printf("%d\n",ans);
	}
	return 0;
}

标签:前缀,re,int,题解,Prefixes,vis,Zero,Max,sim
From: https://www.cnblogs.com/WaterSun/p/CF1748C.html

相关文章

  • 题解 [蓝桥杯 2016 省 B] 交换瓶子
    题目链接本题解讲解环图的做法。要将一个\(1\simn\)的排列通过交换变成\(1\simn\),可以先将\(i\)向\(a_i\)连边,那么最终一定会练成若干个环(每个点只有一个出度,也只有一个入度)。假设交换在同一个环中的节点,一个环显然会变成两个环,也就是说,交换一次最多增加一个环的数量,......
  • 【题解】洛谷 P1003 [NOIP2011 提高组] 铺地毯
    原题链接解题思路如果直接按照题意开一个二维数组来模拟每个点最上面的地毯编号,会发现所占空间最坏情况下约为(2*105)2*4B=4*1010*4B=1.6*1011B≈149GB,程序完全无法运行。但实际上没有必要将每一个点的信息记录下来,只需要记录每一块地毯能覆盖哪些点,再依次判断哪那些地毯可以......
  • 「题解」Codeforces Round 894 (Div. 3)
    A.GiftCarpetProblem题目Sol&Code签到题#include<bits/stdc++.h>#defineN21typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,n,m,a[4];std::strings[N];i......
  • T2回家(home)题解
    T2回家(home)现在啥也不是了,虽然会了逆元,但是对期望概率题还是一窍不通,赛时相当于只推出了\(n=1\)的情况,结果运用到所有情况,理所应当只有20分。题目描述小Z是个路痴。有一天小Z迷路了,此时小Z到家有NN个单位长度。小Z可以进行若干次行动,每次行动小Z有\(\frac12\)的概率向......
  • [ARC035B] アットコーダー王国のコンテスト事情 题解
    前置芝士排列组合分析明显的贪心,第一问与此题思路相似,优先选择做时间少的,可以尽可能让后面的罚时尽量的小。难点在第二问,第二问问的是有几种可能性,有个显然的结论:相同做题时间的题目,位置调换答案仍然相同。那么可以用桶+排列组合来解决:用桶储存这个做题时间的出现次数\(b......
  • AT_abc321_f 题解
    #思路简单动态规划,$dp_i$指当前操作后取和为$i$的球的方案数,每次输出$dp_K$即可。需要注意的是对于每次`+x`操作,计算$dp$数组时要倒着循环。时间复杂度:$O(QK)$。#代码```cpp#include<bits/stdc++.h>usingnamespacestd;longlongdp[5010];intmain(){ longlon......
  • RDP远程登录后全屏,本地的任务栏始终显示的问题解决
    文章目录问题解决参考问题RDP远程登录后全屏,本地的任务栏(TaskBar)始终在下面,遮住了远程桌面的最下面,进行了解决。解决BestsolutionhowtohidelocalTaskbarwhenRDPtoaremotedesktopLaunchTaskManagerRight-click“WindowsExplorer”Select“Restart”Itworkson......
  • CodeForces-1276#B 题解
    正文这是样例1第1组数据的图。让我们观察一下,路径1->6、1->7、2->6、2->7是可行的,所以答案为4。上述路径中好像点4没有贡献?再看看样例1第2组数据的图。发现点1和点4相互之间存在其他路径,无需经过点\(a\)和点\(b\)。综上,我们可以知道:在\(a\)和\(b\)......
  • AT_abc279_g [ABC279G] At Most 2 Colors 题解
    题解\(dp[i]\)表示长度为i的格子的合法涂色数,考虑第\(i\)个怎么放第\(i\)个前面\(k-1\)个位置有2种颜色,则第\(i\)个位置只能放这两种颜色中的一种用合法方案减只有一种的方法,即得两种颜色的方案数而只有一种颜色的方案数,等于\(f[i-k+1]\),此时,让中间的\(k-2\)个......
  • P4839 P 哥的桶 题解
    题目大意有\(n\)个桶,\(m\)次操作。在\(pos\)桶中加入一个\(val\)值,求\([l,r]\)中选任意个桶使得异或和最大,求最大的异或和,注意每个节点是一个桶可以放多个值\(n,m≤5×104\)。题目思路单点修改,区间查询,异或最大值很显然是线段树维护线性基然后这样的复杂度是......