[CSP-S模拟测试]:简单的区间(分治)

题目描述

给定一个长度为$n$的序列$a$以及常数$k$,序列从$1$开始编号。

$$f(l,t)=\sum \limits_{i=l}^ra_i-\max \limits_{i=l}^r\{a_i\}$$
求合法的正整数对$(l,r)$的数量,满足$1\leqslant l<r\leqslant n$,且$k|f(l,r)$。


输入格式

第一行两个正整数$n$和$k$。
第二行包含$n$个正整数,第$i$个正整数表示$a_i$。


输出格式

一行一个正整数,表示答案。


样例

样例输入1:

4 3
1 2 3 4

样例输出1:

3

样例输入2:

4 2
4 4 7 4

样例输出2:

6


数据范围与提示

对于$30\%$的数据,$n\leqslant 3,000$;
对于另外$20\%$的数据,数列$a$为随机生成;
对于$100\%$的数据,$1\leqslant n\leqslant 3\times {10}^5,1\leqslant k\leqslant {10}^6,1\leqslant a_i\leqslant {10}^9$。


题解

考虑分治,但是我的打法跟正解不太一样。

$solve(l,r)$代表左右端点都在$[l,r]$之间的合法区间数量。

显然我们肯定不能依次枚举每个端点,这样的时间复杂度还是$\Theta(n^2)$的,所以我们考虑优化。

我们可以指枚举一侧,然后在处理另一侧的时候计算这一侧的答案即可。

时间复杂度:$\Theta(n\log n)$。

期望的分:$100$分。

实际的分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[300001];
int s[300001];
int maxn[300001],pos[300001];
int t1[10000001],t2[10000001];
long long ans;
void wzc(int l,int r)
{
	if(l==r)return;
	int mid=(l+r)>>1;
	int flag1=1,flag2=mid+1,mx=0;
	s[0]=s[mid]=maxn[0]=0;
	for(int i=mid+1;i<=r;i++)
	{
		if(a[i]>a[maxn[maxn[0]]])maxn[++maxn[0]]=i;
		s[i]=(s[i-1]+a[i])%k;
		t1[(s[i]-a[maxn[maxn[0]]]%k+k)%k]++;
		pos[i]=maxn[maxn[0]];
	}
	maxn[maxn[0]+1]=r+1;
	for(int i=mid;i>=l;i--)
	{
		s[0]=(s[0]+a[i])%k;
		mx=max(mx,a[i]);
		while(flag1<=maxn[0]&&a[maxn[flag1]]<=mx)flag1++;
		while(flag2<maxn[flag1])
		{
			t1[(s[flag2]-a[pos[flag2]]%k+k)%k]--;
			t2[s[flag2++]]++;
		}
		if(flag1<=maxn[0])ans+=t1[(k-s[0])%k];
		ans+=t2[(mx%k-s[0]+k)%k];
	}
	for(int i=mid+1;i<flag2;i++)t2[s[i]]--;
	for(int i=flag2;i<=r;i++)t1[(s[i]-a[pos[i]]%k+k)%k]--;
	wzc(l,mid);
	wzc(mid+1,r);
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	wzc(1,n);
	printf("%lld",ans);
	return 0;
}


rp++

原文地址:https://www.cnblogs.com/wzc521/p/11494378.html

时间: 2024-07-31 10:37:29

[CSP-S模拟测试]:简单的区间(分治)的相关文章

[CSP-S模拟测试]:简单的括号序列(组合数)

题目传送门(内部题82) 输入格式 一行一个字符串$ss$,保证$ss$中只包含$'('$和$')'$. 输出格式 一行一个整数,表示满足要求的子序列数对$10^9+7$的结果. 样例 样例输入1: )(()() 样例输出1: 6 样例输入2: ()()() 样例输出2: 7 样例输入3: ))) 样例输出3: 0 数据范围与提示 样例解释: 第一组样例中,有以下几种子序列满足条件(字符串下标从$1$计数): 删除$1,5$位置的字符,得到$(())$ 删除$1,2,3,4$位置的字符,得到$(

[CSP-S模拟测试]:简单的玄学(数学)

题目描述 有$m$个在$[0,2^n)$内均匀随机取值的整型变量,球至少有两个变量取值相同的概率.为了避免精度误差,假设你的答案可以表示成$\frac{a}{b}$的形式,(其中$(a,b)=1$),你需要输出$a$和$b$对${10}^6+3$取模后的值. 输入格式 第一行两个正整数$n,m$. 输出格式 一行两个整数,它们的含义如题所述. 样例 样例输入1: 3 2 样例输出1: 1 8 样例输入2: 1 3 样例输出2: 1 1 样例输入3: 4 3 样例输出3: 23 128 数据范围与

[CSP-S模拟测试]:简单的填数(贪心+模拟)

题目描述 对于一个长度为$n$,且下标从$1$开始编号的序列$a$,我们定义它是「合法的」,当且仅当它满足以下条件:·$a_1=1$·对于$i\in [1,n),a_i\leqslant a_{i+1}\leqslant a_i+1$且$a_{i+1}$为正整数·对于任意在$a$中出现过的数$v$,记它的出现次数为$s$,则$2\leqslant s\leqslant 5$给定一个长度为$n$的序列$a$,其中有一些位置为$0$,你需要在这些位置上任意填数,使得$a$成为一个合法的序列,并且最大

[CSP-S模拟测试]:简单的期望(DP)

题目描述 从前有个变量$x$,它的初始值已给出. 你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$. 假设最后得到的值为$w$,令$d$为$w$的质因数分解中$2$的次数,求$d$的期望. 输入格式 从文件$exp.in$中读入数据. 第一行三个整数$x,n,p$,含义见题目描述. 输出格式 输出到文件$exp.out$中. 一行一个实数,表示$d$的期望. 如果你的答案与标准答案的误差不超过$10^{−6}$,则判定

[CSP-S模拟测试]:简单的操作(二分图+图的直径)

题目描述 从前有个包含$n$个点,$m$条边,无自环和重边的无向图. 对于两个没有直接连边的点$u,v$,你可以将它们合并.具体来说,你可以删除$u,v$及所有以它们作为端点的边,然后加入一个新点$x$,将它与所有在原图中与u或v有直接连边的点连边. 你需要判断是否能通过若干次合并操作使得原图成为一条链,如果能,你还需要求出这条链的最大长度. 输入格式 从文件$merge.in$中读入数据. 第一行两个正整数$n,m$,表示图的点数和边数. 接下来m行,每行两个正整数$u,v$,表示$u$和$v

csp-s模拟测试93

csp-s模拟测试93 自闭场. $T1$想到$CDQ$,因为复杂度少看见一个$0$打了半年还用了$sort$直接废掉,$T2$,$T3$直接自闭暴力分都没有.考场太慌了,心态不好. 80 02:07:34 0 03:12:11 0 03:11:53 80 03:12:11 没有前途就是垃圾趁早滚回实验二安度晚年吧. A. 序列 $CDQ$不接受反驳. B. 二叉搜索树 最简单的$Dp$都没认真想,太垃圾了,积累一个决策单调性优化$Dp$.一些看似是$n^3$的题可以通过特殊性质优化,还比如以前

csp-s模拟测试94

csp-s模拟测试94 一场简单题,打爆了.$T1$脑抽分解质因数准备分子分母消,想了半天发现$jb$互质直接上天,果断码了高精滚蛋.$T2$无脑手玩大样例,突然灵光一闪想到映射到前$K$大小的区间,$T3$写完暴力准备划水,突然发现特殊性质可写,$10$分钟拯救了$25$分. 80 03:24:46 70 03:24:58 65 03:25:10 215 03:25:10 没办法就是菜,退役也不暝目. A. 凉宫春日的忧郁 转成对数轻松过. B. 漫无止境的八月 取模到$K$大小的区间,$ha

模拟测试(vj)

做这份模拟测试,已经崩溃了,英文看不懂,题意理解错.到结束了只a了第一题,人生陷入了低谷,于是花了一天的时间终于把不会的弄明白了,在这里写一份总结~ T1,简单的模拟,如果打枪打中一支鸟,将这个位置设为0,并向两边扩散,注意这个位置一定要有鸟. 代码~ #include<bits/stdc++.h> using namespace std; int a[30000]; int n,m; int main() { cin>>n; for(int i=1;i<=n;i++) ci

Android单元测试与模拟测试详解

测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabricator differential 发diff时提交需要执行的单元测试,在开发流程上就可以保证远端代码的稳定性). 2. 测什么? 一般单元测试: 列出想要测试覆盖的异常情况,进行验证. 性能测试. 模拟测试: 根据需求,测试用户真正在使用过程中,界面的反馈与显示以及一些依赖系统架构的组件的应用测