[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 ...
随机推荐
- mysql实现“存在即更新,不存在即插入”
方法1:使用replace关键字 replace是insert的增强版,可以实现插入的数据和已存在的数据发生主键或者唯一键重复,则删除已存在的数据,再实现插入,如果不重复,则直接插入数据. 结合Myb ...
- 像这样玩C#【转】,觉得文章写的不错就转来啦!版权不在我
我们玩技术,不是被技术玩.Coding是快乐的,而非苦逼的..Net/C# 这个神器竟然天天有人吐槽.看不下去鸟. 在top10语言中,C#是最优美的语言,没有之一.在top10语言中,C#所可用的标 ...
- Intel processor brand names-Xeon,Core,Pentium,Celeron----Xeon
http://en.wikipedia.org/wiki/Comparison_of_Intel_processors Processor Series Nomenclature Code Name ...
- 资源-DotNet-站点:DotNet 站点列表
ylbtech-资源-DotNet-站点:DotNet 站点列表 1.ASP.NET Web返回顶部 1.1.问卷星 https://www.wjx.cn/sample/service.aspx 1. ...
- Powercli随笔 - PowerCLI script to sequentially Storage vMotion VMs from a CSV File
PowerCLI script to sequentially Storage vMotion VMs from a CSV File This is a PowerCLI script that I ...
- Php 单元测试 phpunit && codecept
Php 单元测试 phpunit && codecept phpunit: Windows版本 整体上说,在 Windows 下安装 PHAR 和手工在 Windows 下安装 Com ...
- chromedriver安装报错
解决方法: 可以使用 npm init -f命令生成package.json,package.json中缺少的字段可以参照模板 package.json进行填充,package.json中的字段 ...
- USACO 6.5 章节 世界上本没有龙 屠龙的人多了也便有了
All Latin Squares 题目大意 n x n矩阵(n=2->7) 第一行1 2 3 4 5 ..N 每行每列,1-N各出现一次,求总方案数 题解 n最大为7 显然打表 写了个先数值后 ...
- 【python】 读写文件
#标准输出 sys.stdout.write() sys.stderr.write() #标准输入 while True : try: line = raw_input().rstrip(); exc ...
- c# 读取和写入excel数据
1. 读取 DataTable GetDataFromExcelByConn(bool hasTitle = false){ OpenFileDialog openFile = new Open ...