题面

我也想过根号分治,但是题目刷得少,数组不敢开,所以还是看题解做的。

这道题目要用到根号分治的思想,可以看看这道题目和我的题解。

题目要求处理一个数组a,支持如下操作。

对一个整数x,对数组长度范围内所有位置( y + x * i )加上一个数,y <= x。

查询区间和

数据范围1e5,使用分块。

处理修改

分块的一大特点就是其已经确定的单次查询复杂度,那么我们可以顺藤摸瓜,以n1/2为分界点推理操作。

对于x>=n1/2,y + x * i 对应范围内位置不超过n1/2个,可以暴力修改原数组。

对于x<n1/2,范围内的修改位置过多,但是x是小于n1/2的。

处理一个辅助数组pre[ i ][ j ]

令modify( x , y )为操作x,y,k加上的值k,那么pre[ i ][ j ]表示 modify(i , 1)+modify(i,2)+...+modify(i,j)

我们修改这个东西,单次操作时间复杂度为n1/2

这个操作在处理询问的时候有用。

处理询问

对于一段询问区间l,r。

先查询其原本的数据和x>=n1/2的修改,这部分已经经过完全修改,可以直接分块求和。

即对于整块加上整块和,散块暴力求和,时间复杂度n1/2

暴力求答案第一部分

if(lb==rb)
for(int j=l;j<=r;j++)
ans+=a[j],ans%=mod;
else{
for(int j=l;j<=lb*len;j++)
ans+=a[j],ans%=mod;
for(int j=lb+1;j<=rb-1;j++)
ans+=b_sum[j],ans%=mod;
for(int j=(rb-1)*len+1;j<=r;j++)
ans+=a[j],ans%=mod;
}

再查询x<n1/2的修改。

这时,发现之前求了一个pre[ i ][ j ]。

对于每个y<=x,我们可以求出对应修改(x,y)在l,r内修改的次数。

如图,我们可以发现,l总处于x*k+y1,r总处于x*( k + t )-y2。

k就是(l-1)/ x,k+t就是 r / x。

我们可以先求出x在一段长为x的区间内的修改总量,即为modify(x,1)+modify(x,2)+...+modify(x,x),这东西我们之前求过,就是pre[ x ][ x ]

那么我们可以求出x在x*k~x*(k+t)内的修改总量,即为pre[ x ][ x ] * t 。

k是(l-1)/x+1,k+t是

这个修改值还需要减去modify(x,1)+modify(x,2)+...+modify(x,y1-1)和 modify(x,y2+1)+modify(x,y2+2)+...+modify(x,x)。

即pre[ x ][ y1 ]和pre[ x ][ x ]-pre[ x ][ y2 ]。

因为这些值都预处理过,所以直接调用,对一个x进行查询的时间复杂度是O(1),x一共有大约n1/2个。

这就是分块很有意思的一个地方!预处理和查询操作相互呼应,最终把单次查询时间复杂度拉到n1/2

求答案第二部分,x的修改值

for(int j=1;j<len;j++){
lb=(l-1)/j+1,rb=(r-1)/j+1;
if(lb==rb)
ans-=pre[j][(l-1)%j],ans%=mod,ans+=pre[j][(r-1)%j+1],ans%=mod;
else
ans=(ans+1ll*(rb-lb+1)*pre[j][j]%mod-suf[j][(r-1)%j+2]-pre[j][(l-1)%j])%mod;
}

于是查这些修改值的时间是n1/2

#include<bits/stdc++.h>
using namespace std;
const int h=200010;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') w= -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
int mod=1e9+7;
int n,m;
int a[h];
int b_sum[h];
int len;
int pre[2010][2010];
int suf[2010][2010];
int get_pos(int x){
return (x-1)/len+1;
}
int main(){
n=read(),m=read();
len=120;
for(int i=1;i<=n;i++)
a[i]=read(),b_sum[get_pos(i)]+=a[i]%mod,b_sum[get_pos(i)]%=mod;
int op,x,y,z;
for(int i=1;i<=m;i++){
op=read(),x=read(),y=read();
if(op==1){
z=read();
if(x>=len)
for(int j=y;j<=n;j+=x)
a[j]+=z,a[j]%=mod,b_sum[get_pos(j)]+=z,b_sum[get_pos(j)]%=mod;
else{
for(int j=y;j<=x;j++)
pre[x][j]+=z,pre[x][j]%=mod;
for(int j=1;j<=y;j++)
suf[x][j]+=z,suf[x][j]%=mod;//这里的suf就是后缀和,suf[x][i]等价于pre[x][x]-pre[x][i-1]
}
}
else{
int l=x,r=y,lb=get_pos(x),rb=get_pos(y);
int ans=0;
if(lb==rb)
for(int j=l;j<=r;j++)
ans+=a[j],ans%=mod;
else{
for(int j=l;j<=lb*len;j++)
ans+=a[j],ans%=mod;
for(int j=lb+1;j<=rb-1;j++)
ans+=b_sum[j],ans%=mod;
for(int j=(rb-1)*len+1;j<=r;j++)
ans+=a[j],ans%=mod; } for(int j=1;j<len;j++){
lb=(l-1)/j+1,rb=(r-1)/j+1;
if(lb==rb)
ans-=pre[j][(l-1)%j],ans%=mod,ans+=pre[j][(r-1)%j+1],ans%=mod;
else
ans=(ans+1ll*(rb-lb+1)*pre[j][j]%mod-suf[j][(r-1)%j+2]-pre[j][(l-1)%j])%mod;
}
printf("%d\n",(ans%mod+mod)%mod);
}
} return 0;
}

完整代码

总的时间复杂度是m*n1/2,理论上正确。

因为常数因子过大,无法通过本题,进一步提速请看Ynoi2011初始化卡常优化

洛谷P5309 Ynoi 2011 初始化 题解的更多相关文章

  1. 洛谷P1783 海滩防御 分析+题解代码

    洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...

  2. 洛谷P4047 [JSOI2010]部落划分题解

    洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...

  3. 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)

    洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...

  4. 洛谷10月月赛II题解

    [咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...

  5. [洛谷P1823]音乐会的等待 题解(单调栈)

    [洛谷P1823]音乐会的等待 Description N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没 ...

  6. BZOJ2527 & 洛谷3527:[Poi2011]Meteors——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

  7. 洛谷 p1516 青蛙的约会 题解

    dalao们真是太强了,吊打我无名蒟蒻 我连题解都看不懂,在此篇题解中,我尽量用语言描述,不用公式推导(dalao喜欢看公式的话绕道,这篇题解留给像我一样弱的) 进入正题 如果不会扩展欧里几德的话请先 ...

  8. 洛谷p2370yyy2015c01的U盘题解

    没什么特殊的想法 就是看自己很久没有更新关于题解类的文章了而已 (其实这是我好久之前做的, 只是把它从洛谷博客搬到了这里而已) 题目 首先分析题目要二分 他长成这个亚子太二分了 所以就要二分 最好是先 ...

  9. 2019.06.17课件:[洛谷P1310]表达式的值 题解

    P1310 表达式的值 题目描述 给你一个带括号的布尔表达式,其中+表示或操作|,*表示与操作&,先算*再算+.但是待操作的数字(布尔值)不输入. 求能使最终整个式子的值为0的方案数. 题外话 ...

随机推荐

  1. bind搭建内网DNS服务器架构(主从、子域授权、DNS转发器)

    实验目的 模拟企业DNS服务架构服务器及原理 实验环境准备 实验架构图 实验设备 DNS服务器4台 主服务器master(centos8):IP_192.168.100.30, 从服务器slave(r ...

  2. OpenJudge 1.5.24 正常血压

    24:正常血压 总时间限制: 1000ms 内存限制: 65536kB 描述 监护室每小时测量一次病人的血压,若收缩压在90 - 140之间并且舒张压在60 - 90之间(包含端点值)则称之为正常,现 ...

  3. BI如何实现用户身份集成自定义安全程序开发

    统一身份认证是整个 IT 架构的最基本的组成部分,而账号则是实现统一身份认证的基础.做好账号的规划和设计直接决定着企业整个信息系统建设的便利与难易程度,决定着系统能否足够敏捷和快速赋能,也决定了在数字 ...

  4. OSI模型 TCP/IP协议

    常见术语 网络相关的术语 1.拓扑:物理拓扑-----体现了设备之间的连接关系 逻辑拓扑----设备之间的通信关系 2.数据载荷:传递的实际信息 3.报文(PDU--协议数据单元) 4.数据头部的作用 ...

  5. SDUT 2022 Autumn Team Contest 7th

    1.J题:给你T组数据,每一组数据给你一个区间,让你求这个区间的范围,区间的起始时间和终止时间可能被包含或重复 思路:思路的话,就是直接把给定的两个区间的之间的数包括端点存到vector去重,然后直接 ...

  6. ORM增删改查并发性能测试

    这两天在对一些ORM进行性能测试(涉及SqlSugar.FreeSql.Fast.Framework.Dapper.LiteSql),测试用的是Winform程序,别人第一眼看到我的程序,说,你这测试 ...

  7. MAC Golang环境搭建

    1. 下载golang 下载地址:https://golang.google.cn/dl/ 根据MAC左上角苹果图标->关于本机,即可查看芯片类型 2. 安装golang 在 下载 中双击 下载 ...

  8. [深度学习]-Dataset数据集加载

    加载数据集dataloader from torch.utils.data import DataLoader form 自己写的dataset import Dataset train_set = ...

  9. Kubernetes 控制器

    在实际使用的时候并不会直接使用 Pod,而是会使用各种控制器来满足我们的需求,Kubernetes 中运行了一系列控制器来确保集群的当前状态与期望状态保持一致,它们就是 Kubernetes 的大脑. ...

  10. Solutions:如何运用Elastic App Search快速建立出色的React搜索体验

    建立搜索体验是一项艰苦的工作. 乍一看似乎很容易:建立一个搜索栏,将数据放入数据库,然后让用户输入对该数据库的查询. 但是,在数据建模,底层逻辑以及(当然)总体设计和用户体验方面,有很多事情要考虑. ...