初次接触分块思想

2024-03-27 22:58
文章标签 思想 接触 分块 初次

本文主要是介绍初次接触分块思想,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在练习mobius反演的时候有一题需要用分块的思想来优化,于是第一次听说了分块思想。比较有名的当属号称可以解决所有不修改、离线查询问题的莫队算法。几乎所有的莫队算法的介绍都和[BZOJ]2038 小Z的袜子有关,相关大神博客:http://www.cnblogs.com/kuangbin/p/3263483.html
先来个稍简单的分块题:


codeforces 86 D. Powerful array

http://codeforces.com/problemset/problem/86/D
大意:给定一串数字,给定一系列询问,问在相应区间内 Ks·Ks·s     的和,其中Ks是K数字S在区间内出现的次数。
分块解决,相关证明:

Let's sort the query intervals according to the following rule: first come the intervals with the left ends in Q_1, then the intervals with the left ends in Q_2, and so on. And if the left ends of the two queries belong to the same part, then the interval with the more left right end is assumed to be smaller.
In order to prove the stated asymptotic behavior we will follow the steps of the left and the right ends independently. We note that the left ends that belong to the same Q_i make <= n / p steps, and transition to Q_{i+1} costs no more than 2 * n / p steps. Therefore the left ends make <= n/p * n + 2*n steps (the second summand is O(n), and it's negligible).
The right ends in the common group move only to the right, and this proves <= n * p steps (during the whole process) estimate. We will estimate the transition to the next Q_i at no more than n steps, so overall we get < = 2 * n * p steps.
Thus, the total number of steps is no more than (n / p * n + 2 * n * p). Now we choose p = sqrt(n) which proves the statement.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=2e5+10,M=1e6+10;
int a[N],cnt[M];
struct node{int x,y,l,dex;
}edge[N];
int cmp(node a,node b){return a.l<b.l||(a.l==b.l&&a.y<b.y) ;
}
LL ans,res[N];
int L,R;
void query(int x,int y,int dex){if(dex){for(int i=L;i<x;i++){cnt[a[i]]--;ans=ans-((cnt[a[i]]<<1)+1)*a[i];}for(int i=x;i<L;i++){ans=ans+((cnt[a[i]]<<1)+1)*a[i];cnt[a[i]]++;}for(int i=R+1;i<=y;i++){ans=ans+((cnt[a[i]]<<1)+1)*a[i];cnt[a[i]]++;}for(int i=y+1;i<=R;i++){cnt[a[i]]--;ans=ans-((cnt[a[i]]<<1)+1)*a[i];}}else {for(int i=x;i<=y;i++) {ans=ans+((cnt[a[i]]<<1)+1)*a[i];cnt[a[i]]++;}}L=x;  R=y;
}
int main()
{//freopen("cin.txt","r",stdin);int n,t;while(cin>>n>>t){int len=sqrt(1.0*n);memset(cnt,0,sizeof(cnt));for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=0;i<t;i++){scanf("%d%d",&edge[i].x,&edge[i].y);edge[i].dex=i;edge[i].l=(edge[i].x-1)/len;}sort(edge,edge+t,cmp);ans=0;for(int i=0;i<t;i++){query(edge[i].x,edge[i].y,i);res[edge[i].dex]=ans;}for(int i=0;i<t;i++){printf("%I64d\n",res[i]);}}return 0;
}

这是那道和mobius相关的题:

spoj  PGCD - Primes in GCD Table(mobius+分块)
http://www.spoj.com/problems/PGCD/en/
大意: 在一张(a,b)的表格中,填写完整对应交点值gcd(i,j)。问填写了多少次的素数。
即求解最大公约数是素数的组合有多少个。
莫比乌斯反演:
其中d就是各种素数。求解

学习了大神的博文: http://blog.csdn.net/jayye1994/article/details/12621589
设 
那么最开始处理时,sum[i*pri[j]]+=sum[i];  再前缀和处理.
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N=1e7+10;
int mu[N],pri[N/10],cnt=0;
bool vis[N];
LL sum[N];
void getmu(){mu[1]=1;for(int i=2;i<N;i++){if(!vis[i]){mu[i]=-1;pri[cnt++]=i;}for(int j=0;j<cnt&&pri[j]*i<N;j++){vis[i*pri[j]]=1;if(i%pri[j]==0){mu[i*pri[j]]=0;break;}else mu[i*pri[j]]=-mu[i];}}for(int i=1;i<N;i++){if(mu[i]){for(int j=0;i*pri[j]<N&&j<cnt;j++){sum[i*pri[j]]+=mu[i];}}}for(int i=1;i<N;i++){sum[i]+=sum[i-1]*1LL;}
}
int main()
{//freopen("cin.txt","r",stdin);int a,b,t;getmu();cin>>t;while(t--){scanf("%d%d",&a,&b);if(a>b){a=a^b;  b=a^b;  a=a^b;}LL ans=0;for(int i=1;i<=a;i++){  //10/4=2;  10/2=5;int t1=a/i,t2=b/i;int next=min(a/t1,b/t2);ans=ans+1LL*t1*t2*(sum[next]-sum[i-1]);i=next;}printf("%lld\n",ans);}return 0;
}




这篇关于初次接触分块思想的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853675

相关文章

16.Spring前世今生与Spring编程思想

1.1.课程目标 1、通过对本章内容的学习,可以掌握Spring的基本架构及各子模块之间的依赖关系。 2、 了解Spring的发展历史,启发思维。 3、 对 Spring形成一个整体的认识,为之后的深入学习做铺垫。 4、 通过对本章内容的学习,可以了解Spring版本升级的规律,从而应用到自己的系统升级版本命名。 5、Spring编程思想总结。 1.2.内容定位 Spring使用经验

海量数据处理经典思想

第一部分、十五道海量数据处理 1. 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?     方案1:可以估计每个文件安的大小为50G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。 遍历文件a,对每个url求取,然后根据所取得的值将url分别存储到1000个小文件(

第一次接触Swing

学习java版的HslCommunication发现使用的是Swing,所以了解了一下~ 了解: Swing是Java的标准库(Java Foundation Classes, JFC)的一部分,用于构建桌面应用程序的图形用户界面(GUI)。它是Java AWT(Abstract Window Toolkit)的增强版,提供了更多的组件、更好的外观和感觉,以及更丰富的功能。Swing使用

每日一题——Python代码实现力扣1. 两数之和(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 菜鸡写法 代码分析 时间复杂度分析 空间复杂度分析 改进建议 我要更强 方法1: 使用哈希表(字典) 方法2: 排序和双指针 方法3: 使用集合(仅适用于特殊情况) 哲学和编程思想

每日一题——Python代码实现PAT乙级1048 数字加密(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 初次尝试  再次尝试 代码点评 代码结构 时间复杂度 空间复杂度 优化建议 我要更强 优化建议 完整代码及注释 时间复杂度和空间复杂度分析 进一步优化 哲学和编程思想 模块化

RabbitMQ和Kafka设计思想的感性辨析

RabbitMQ和Kafka架构图 1. 设计初衷不完全相同 RabbitMQ是消息分发中间件 包收包送,服务很周到。 设计初衷:单播,消息一对一,每条消息只会被发送一个消费者(当然也可以扩展,如果想让多个消费者消费同一条消息,就得这条消息复制成多份放到多个Queue)。Kafka是消息存储和订阅中间件 自己放自己取,只负责提供场地,其它的全自助。 设计初衷:广播,消息一对多,凡是

洛谷 P10584 [蓝桥杯 2024 国 A] 数学题(整除分块+杜教筛)

题目 思路来源 登录 - Luogu Spilopelia 题解 参考了两篇洛谷题解,第一篇能得出这个式子,第二篇有比较严格的复杂度分析 结合去年蓝桥杯洛谷P9238,基本就能得出这题的正确做法 代码 #include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<map>#include<uno

屁股决定脑袋,思想决定高度

转眼不知不觉来到新公司近三个月了,好久没有静下心写博客了 最近看欢乐颂安迪说的有句话很好,每一个管理者并不在乎你因为什么客观原因导致没完成任务,他更在乎交给你什么任务。你完成的结果如何。是啊,我们在职场与其抱怨这个任务是因为什么原因导致流产,不如多想想解决办法。作为员工我们更应该想想对方有什么需求,在实际工作中多从这些方面思考问题。 1欢乐颂安迪的话引起设计模式的思考 1.1单一职责原则1.2

支撑编程理论的三大思想②简洁

是什么 对代码而言,简洁就是消除了"多余的复杂性"后的状态。这里所说的“多余的复杂性”不是反映了目标(代码要达成的目的)复杂程度的复杂性,而是指在修改代码的过程中遗留下来的痕迹所带来的复杂性。 为什么 “多余的复杂性”不具有任何价值。这类复杂性会阻碍代码正常运行,提高修改代码的难度,损害软件的价值。它会给代码埋下祸根。 消除“多余的复杂性”可以让代码变得简洁。这样一来,阅读、使用、修改代码

支撑编程理论的三大思想①交流

是什么 代码也是一种给人看的文档,而文档的本质在于交流。 在编程中,良好的交流意味着读代码人能够理解、修改和使用代码。 为什么 顺利的开发源于顺利的交流。 软件开发大部分成本是在完成以后产生的,这部分就是维护成本。 要想节约成本,就要提高代码的可读性。这是因为程序员之间是需要通过代码进行交流。读代码的时间要多余写代码的时间。 另外,在开发阶段程序员也要一边回顾前面的代码,一边写新代码