题解

签到题

求区间和为 \(k\) 的倍数的区间,我们可以转化为求左右两个端点,其前缀和相等

对于区间最大值,我们可以把其转化为一个值,它能向左,向右扩展的最远边界,一个单调栈即可

我们设一个值 \(i\),它能扩展的左右边界分别为 \(l_i,r_i\) 那么我们将 \(l_i~r_i\) 分为两部分,\(l_i~i\),\(i~r_i\)

枚举较小的那一段(可以证明总复杂度为 \(\mathcal O(nlogn)\) ),在另一段寻找前缀和等于此前缀和加 \(num_i\) 的个数,用一颗动态开点线段树即可

注意:此种做法边界要卡得很细致

Code:
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
template<typename T>inline void read(T &x) {
ri f=1;x=0;register char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
x=f?x:-x;
}
}
using IO::read;
namespace nanfeng{
#define cmax(x,y) ((x)>(y)?(x):(y))
#define cmin(x,y) ((x)>(y)?(y):(x))
#define FI FILE *IN
#define FO FILE *OUT
static const int N=3e5+7,K=1e6+1;
int num[N],r[N],l[N],st[N],sum[N],nm[N],ans,tp,n,k;
struct Segmenttree{
#define ls(x) T[x].l
#define rs(x) T[x].r
#define up(x) T[x].nm=T[ls(x)].nm+T[rs(x)].nm
struct seg{int l,r,nm;}T[K*20];
int rt[K],tot;
void update(int &x,int p,int l,int r) {
if (!x) x=p(tot);
if (l==r) {p(T[x].nm);return;}
int mid(l+r>>1);
if (p<=mid) update(ls(x),p,l,mid);
else update(rs(x),p,mid+1,r);
up(x);
}
int query(int x,int l,int r,int lt,int rt) {
if (!x) return 0;
if (l<=lt&&rt<=r) return T[x].nm;
int mid(lt+rt>>1),res(0);
if (l<=mid) res+=query(ls(x),l,r,lt,mid);
if (r>mid) res+=query(rs(x),l,r,mid+1,rt);
return res;
}
}T;
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
read(n),read(k);
for (ri i(1);i<=n;p(i)) {
read(nm[i]);num[i]=nm[i]%k;
sum[i]=(sum[i-1]+num[i])%k;
T.update(T.rt[sum[i]],i,1,n);
while(tp&&nm[st[tp]]<=nm[i]) r[st[tp--]]=i-1;
l[i]=st[tp]+1;
st[p(tp)]=i;
}
while(tp) r[st[tp--]]=n;
for (ri i(1);i<=n;p(i)) {
if (i==l[i]&&i==r[i]) continue;
if (i-l[i]<=r[i]-i) {
for (ri j(l[i]);j<i;p(j))
ans+=T.query(T.rt[(sum[j-1]+num[i])%k],i,r[i],1,n);
if (i<r[i]) ans+=T.query(T.rt[sum[i]],i+1,r[i],1,n);
} else {
for (ri j(i+1);j<=r[i];p(j))
if (l[i]-1) ans+=T.query(T.rt[(sum[j]-num[i]+k)%k],l[i]-1,i-1,1,n);
else {
ri tmp=(sum[j]-num[i]+k)%k;
ans+=T.query(T.rt[tmp],l[i],i-1,1,n);
if (!tmp) p(ans);
}
if (l[i]-1) ans+=T.query(T.rt[sum[i-1]],l[i]-1,i-2,1,n);
else {
if (i-2) ans+=T.query(T.rt[sum[i-1]],1,i-2,1,n);
if (!sum[i-1]) p(ans);
}
}
}
printf("%d\n",ans);
return 0;
}
}
int main() {return nanfeng::main();}

官方题解做法,为 \(\mathcal O(nlogn)\) 复杂度较优,但其实没什么太大区别

NOIP 模拟 $12\; \text{简单的区间}$的更多相关文章

  1. NOIP 模拟 $12\; \text{简单的玄学}$

    题解 有些难度 对于 \(30pts\) 直接暴力 对于 \(70pts\) 发现规律 \(2^n-a\) 与 \(a\;\;(a\in [1,2^n))\) 分解质因数后,\(2\) 的次数相同 \ ...

  2. NOIP 模拟 $12\; \text{简单的填数}$

    题解 一个纯的贪心,被我搞成 \(dp\) 了,最后把错解删掉了,骗了 \(10pts\) 考虑如何贪心,设置一种二元组 \((x,l)\),\(x\) 表示当前值,\(l\) 表示当前最长连续长度. ...

  3. noip模拟12[简单的区间·简单的玄学·简单的填数]

    noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...

  4. (译文)12个简单(但强大)的JavaScript技巧(二)

    原文链接: 12 Simple (Yet Powerful) JavaScript Tips 其他链接: (译文)12个简单(但强大)的JavaScript技巧(一) 强大的立即调用函数表达式 (什么 ...

  5. (译文)12个简单(但强大)的JavaScript技巧(一)

    原文连接: 12 Simple (Yet Powerful) JavaScript Tips 我将会介绍和解析12个简单但是强大的JavaScript技巧. 这些技巧所有的JavaScript程序员都 ...

  6. 2021.5.22 noip模拟1

    这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...

  7. NOIP模拟

    1.要选一个{1,2,...n}的子集使得假如a和b在所选集合里且(a+b)/2∈{1,2,...n}那么(a+b)/2也在所选集合里 f[i]=2*f[i-1]-f[i-2]+g[i] g[n]:选 ...

  8. ubuntu 12.04 简单配置samba服务,实现主机与虚拟机互通(设置Windows虚拟盘)

    环境: virtualbox ubuntu12.04 首先,如果你到这步了,说明你的window与linux的网络已经配好了,他们之间是可以互相Ping通的,如果没有,请看我以前的文章 由于我linu ...

  9. 7.22 NOIP模拟7

    又是炸掉的一次考试 T1.方程的解 本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判..暴力掉了40分. 首先a+b=c,只有一组解. 然后是a=1,b=1,答案是c-1 ...

随机推荐

  1. buu SimpleRev

    一.发现是elf文件,拖入ida,然后直接找到了关键函数 点击那个Decry()函数 二.逻辑还是很清晰的,而我是卡在这里v1的逆算法,感觉学到了很多,其实爆破就足够了 这里大小写可以一起写上 tex ...

  2. sqlplus 删除^H处理

    1.在oracle用户下更改 2.在".profile"或者"~/.bash_profile"添加 stty erase ^H 3.wq,保存退出 stty时一 ...

  3. 脱离OBDeploy工具,手工部署OceanBase方法

    [简介] OBDeploy是OceanBase集群部署的工具,可以通过简单的几行命令,就能快速的进行OceanBase部署.但对于初学者来讲,可能会比较困惑,Deploy到底做了哪些事情?里面的具体步 ...

  4. JM操作数据库

    [前言] 为什么要去直连数据库,去操作数据库? 因为在我们做自动化的时候,或者在大批量准备数据的时候,自动化的时候有时候会生成很多条页面上,接口上无法删除的数据,那么就很有很多的测试数据遗留在系统上, ...

  5. scrapy::Max retries exceeded with url

    运行scrapy时出错这个错误:Max retries exceeded with url解决方法: img1=requests.get(url=aa,headers=header1,timeout= ...

  6. VirtualBox 修改Android x86虚拟机的分辨率

    首先说明一下,本人使用的是Windows下的VirtualBox,android x86使用的是9.0-r2版本 一.查看virtualbox中已有的分辨率 启动虚拟机后,连续按两次E键,进入下面页面 ...

  7. windows 查看端口号,关闭端口进程

    1.打开cmd,输入:netstat -ano | findstr 8080,根据端口号查找对应的PID.结果如下: 2.根据PID找进程名称,输入命令:tasklist | findstr 1789 ...

  8. Cesium局部区域精细瓦片数据下载技巧

    当Cesium加载局部的目标地区(如中国某个市)的0-18层或更高层数据时,当缩小到zoom较小时可能地球有部分区域(如南半球或左半球)无瓦片覆盖. 为使得整个地球有瓦片覆盖,可利用以下技巧下载瓦片: ...

  9. StringIO和BytesIO的用法

    数据读写有两种方式: 1.直接读写.案例 import openpyxl def write_excel(): f = openpyxl.Workbook() # 创建工作簿 # sheet1 = f ...

  10. 以两种异步模型应用案例,深度解析Future接口

    摘要:本文以实际案例的形式分析了两种异步模型,并从源码角度深度解析Future接口和FutureTask类. 本文分享自华为云社区<[精通高并发系列]两种异步模型与深度解析Future接口(一) ...