[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++
[CSP-S模拟测试]:简单的区间(分治)的更多相关文章
- noip模拟12[简单的区间·简单的玄学·简单的填数]
noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...
- [CSP-S模拟测试]:简单的括号序列(组合数)
题目传送门(内部题82) 输入格式 一行一个字符串$ss$,保证$ss$中只包含$'('$和$')'$. 输出格式 一行一个整数,表示满足要求的子序列数对$10^9+7$的结果. 样例 样例输入1: ...
- [CSP-S模拟测试]:Revive(点分治)
题目背景 $Sparkling\ ashes\ drift\ along\ your\ flames \\ And\ softly\ merge\ into\ the\ sky$ 题目传送门(内部题1 ...
- [CSP-S模拟测试]:蛋糕(区间DP)
题目传送门(内部题34) 输入格式 第一行,一个正整数$n$.第二行,$n$个正整数$a_i$,保证$a_i$互不相等. 输出格式 一行一个整数表示间宫卓司得到的蛋糕大小总和的最大值. 样例 样例输入 ...
- [CSP-S模拟测试]:简单计算(数学)
题目传送门(内部题104) 输入格式 第一行一个正整数$T$,表示该测试点内的数据组数,你需要对该测试点内的$T$组数据都分别给出正确的答案才能获得该测试点的分数. 接下来$T$组数据,每组数据一行两 ...
- [CSP-S模拟测试]:简单的操作(二分图+图的直径)
题目描述 从前有个包含$n$个点,$m$条边,无自环和重边的无向图. 对于两个没有直接连边的点$u,v$,你可以将它们合并.具体来说,你可以删除$u,v$及所有以它们作为端点的边,然后加入一个新点$x ...
- [CSP-S模拟测试]:简单的期望(DP)
题目描述 从前有个变量$x$,它的初始值已给出. 你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$. 假设最后得到的值为$ ...
- [CSP-S模拟测试]:简单的序列(DP)
题目描述 从前有个括号序列$s$,满足$|s|=m$.你需要统计括号序列对$(p,q)$的数量. 其中$(p,q)$满足$|p|+|s|+|q|=n$,且$p+s+q$是一个合法的括号序列. 输入格式 ...
- [CSP-S模拟测试]:简单的填数(贪心+模拟)
题目描述 对于一个长度为$n$,且下标从$1$开始编号的序列$a$,我们定义它是「合法的」,当且仅当它满足以下条件:·$a_1=1$·对于$i\in [1,n),a_i\leqslant a_{i+1 ...
随机推荐
- <三剑客> 老二:sed命令用法
sed命令的用法: sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space ...
- CF704E Iron Man
CF704E Iron Man 经过不懈(抄题解)努力之后,终于AC了此题. 说起来很简单. 考虑一个链上的情况, 建立直角坐标系. 横坐标是t,纵坐标是距离链开头的距离d m个路径就是一个线段 那么 ...
- Dealing with exceptions thrown in Application_Start()
https://blog.richardszalay.com/2007/03/08/dealing-with-exceptions-thrown-in-application_start/ One a ...
- IDEA默认快捷键
idea常用快捷键大全 Idea常用快捷键大全,拿小本本记下来,忘记了可以方便查找.编写代码Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最 ...
- 52-python基础-python3-列表-常用列表方法- reverse()方法
reverse()方法 永久性地修改列表元素的排列顺序,但可随时恢复到原来的排列顺序,为此只需对列表再次调用reverse() 即可. 实例:
- int类型转换舍入问题
一,看代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sy ...
- windows修改docker的默认存放位置
docker默认存储到c盘,我需要移动到其他盘. 参考了网上很多资料,结果要么移动不了,要么重启docker就回到c盘了. 最后参考docker的官方论坛,找到了解决方案.https://forums ...
- 八、hibernate的查询(HQL)
HQL:Hibernate Query Language 提供更加丰富灵活.更为强大的查询能力 HQL更接近SQL语句查询语法 面向对象的查询 "from Children where ci ...
- IDEA compile successfully many errors still occur
Compile and install successfully with maven in IDEA, but error prompt still popup. Your local enviro ...
- SQL数据库—<8>触发器
触发器:一.什么是触发器? 一段SQL代码,挂到某个表的某个增.删.改的操作上. 当这个表执行相应的操作时,就会触发这段相应的SQL代码.触发器与存储过程的区别:1.存储过程是独立于表存在 ...