牛客CSP-S提高组赛前集训营2 C-维护序列(分块)

2023-10-29 10:50

本文主要是介绍牛客CSP-S提高组赛前集训营2 C-维护序列(分块),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述 n < = 1 e 5 n<=1e5 n<=1e5,时限 6 s 6s 6s
脑阔癌。
真的就是大分块就完了。
考场往上一看6s时限,考虑分块,发现这个存答案很困难,卡空间,考虑分块

跨块询问的很简单,维护每种颜色( a i a_i ai)在每个块内的最左位置和最右位置,然后就可以简单 O ( n S ) O(\frac nS) O(Sn)计算跨块的答案了。
跨块的修改就是打区间覆盖标记。
块内的答案一看(可能?)就只能直接维护 O ( S 2 ) O(S^2) O(S2)
额,我指的是每次修改散块(边界的块)的时候可以暴力 O ( S 2 ) O(S^2) O(S2)
所以复杂度为 O ( q n S + q S 2 + S 2 n S ) O(q\frac nS + qS^2 + S^2\frac nS) O(qSn+qS2+S2Sn)
q q q n n n同阶,令 S = O ( n 1 3 ) S = O(n^{\frac 13}) S=O(n31),平衡复杂度为 O ( n 5 3 ) O(n^{\frac 53}) O(n35)
所以貌似所有可以 n 2 n^2 n2的题都可以不用脑子的用这个方法写 n 5 3 n^\frac 53 n35
但是空间复杂度,因为我们需要对每个块的颜色离散化,需要建立引索,所以是 O ( n 2 S ) O(\frac {n^2} S) O(Sn2)的,所以需要 S = 200 S = 200 S=200左右,实测 S = 100 S=100 S=100没有 S = 200 S=200 S=200快。

出题人:可以 O ( n 3 2 ) O(n^{\frac 32}) O(n23)
对于两端的零散块,我们需要重建这两个块。举左侧块为例,设左侧块区间为 [ u , v ] [u,v] [u,v],要修改 [ l , v ] [l,v] [l,v] 之间的点为颜色 x x x。然后我们要更新块内的答案。注意到只有 x x x [ l , v ] [l,v] [l,v]中出现的颜色的答案会有改变,所以就用这些颜色去枚举块内其他颜色更新答案。这里均摊出现的颜色个数是 O ( 1 ) \mathcal{O}(1) O(1)的,然后每种颜色都需要枚举块内其它元素,因此单次操作复杂度仍然为均摊 O ( n ) \mathcal{O}(\sqrt n) O(n )
但是只快了 1 4 \frac 14 41

A C C o d e O ( n 5 3 ) \rm AC\ Code\ O(n^{\frac 53}) AC Code O(n35)

#include<bits/stdc++.h>
#define maxn 100005
#define S 200
#define B maxn/S+5
#define inf 0x3f3f3f3f
using namespace std;char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
void read(int &res){char ch;for(;!isdigit(ch=getc()););for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
int n,m,f,a[maxn],St[B],Ed[B],ib[maxn];
int L[B][S],R[B][S],Bans[B][S][S],inb[B][maxn],rnb[B][S],tp[B],tg[B],Pr[S];inline void reset(int b){int *in = inb[b] , *rn = rnb[b] , &tp=::tp[b] , *L = ::L[b] , *R = ::R[b];for(;tp;) memset(Bans[b][tp],0x3f,sizeof Bans[b][tp]),in[rn[tp--]] = 0;for(int i=St[b],r=Ed[b]+1;i!=r;i++){if(!in[a[i]]) rn[in[a[i]]=++tp]=a[i],L[tp]=R[tp]=i;int na = in[a[i]];R[na] = Pr[na] = i;for(int j=1,r=tp+1;j!=r;j++)Bans[b][j][na] = Bans[b][na][j] = min(Bans[b][na][j],i-Pr[j]);}for(int i=1,r=tp+1;i!=r;i++) Pr[i]=-inf;
}int main(){memset(Pr,-0x3f,sizeof Pr);memset(Bans,0x3f,sizeof Bans);read(n),read(m),read(f);for(int i=1;i<=n;i++) read(a[i]),ib[i]=((i-1)/S);for(int i=0;i<=ib[n];i++) St[i]=i*S+1,Ed[i]=min((i+1)*S,n),reset(i);for(int op,l,r,x,ans=0;m--;){read(op),read(l),read(r);if(f) l^=ans,r^=ans;if(op==1){read(x);if(f) x^=ans;int ll = ib[l] , lr = ib[r];if(tg[ll]){for(int i=St[ll],r=tg[ll],d=Ed[ll]+1;i!=d;i++) a[i]=r;tg[ll] = 0;}if(tg[lr]){for(int i=St[lr],r=tg[lr],d=Ed[lr]+1;i!=d;i++) a[i]=r;tg[lr] = 0;}if(ll == lr){for(int i=l,d=r+1;i!=d;i++) a[i] = x;reset(ll);}else{for(int i=l,d=Ed[ll]+1;i!=d;i++) a[i]=x;for(int i=St[lr],d=r+1;i!=d;i++) a[i]=x;reset(ll),reset(lr);for(int i=ll+1;i!=lr;i++) tg[i]=x;}}else{ans = inf;int prl=-inf,prr=-inf;for(int i=0,d=ib[n]+1;i!=d;i++)if(tg[i]){if(tg[i] == l){prl = Ed[i] , ans = min(ans , St[i]-prr);if(l == r){ ans=0; break; }}else if(tg[i] == r) prr = Ed[i] , ans = min(ans , St[i]-prl);}else{int na = inb[i][l] , nb = inb[i][r] , tl = prl , tr = prr;(na && nb) ? ans = min(ans , Bans[i][na][nb]) : 0;(na) ? ans = min(ans , L[i][na] - tr) , prl = R[i][na] : 0;(nb) ? ans = min(ans , L[i][nb] - tl) , prr = R[i][nb] : 0;}if(ans > n) ans = -1;printf("%d\n",ans);ans = max(ans , 0);}}
}

这篇关于牛客CSP-S提高组赛前集训营2 C-维护序列(分块)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/300137

相关文章

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

如何提高 GitHub 的下载速度

如何提高 GitHub 的下载速度 文章目录 如何提高 GitHub 的下载速度1. 注册账号2. 准备好链接3. 创建仓库4. 在码云上下载代码5. 仓库更新了怎么办 一般来说,国内的朋友从 GitHub 上面下载代码,速度最大是 20KB/s,这种龟速,谁能忍受呢? 本文介绍一种方法——利用“码云”,可以大大提高下载速度,亲测有效。 1. 注册账号 去“码云”注册一

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

day-50 求出最长好子序列 I

思路 二维dp,dp[i][h]表示nums[i] 结尾,且有不超过 h 个下标满足条件的最长好子序列的长度(0<=h<=k),二维数组dp初始值全为1 解题过程 状态转换方程: 1.nums[i]==nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h]+1) 2.nums[i]!=nums[j],dp[i,h]=Math.max(dp[i,h],dp[j,h-1