题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5381

还没学过莫队算法。。。。网上也找不到莫队算法的论文,只能勉强看着别人的代码打下来。。。

稍微介绍下莫队算法:

能使用莫队算法的前提是这样的--如果我们已知[l,r]的答案,能在O(1)时间得到[l + 1,r]的答案以及[l,r - 1]的答案,即可使用莫队算法。时间复杂度为O(n * sqrt(n))。如果求[l + 1,r]和[l,r - 1]要在O(logn)下完成,则时间复杂度是O(n * sqrt(n) * logn)。   PS:莫队算法一般处理离线无修改的区间询问

在转移复杂度是O(1)的情况下,已知[l,r]要求[l',r']的答案,那么我们可以在O(|l - l'| + |r - r'|)内求得。

莫队在论文中使用了二维曼哈顿距离最小生成树,而这个东西要用到区域划分法+梳妆数组or线段树维护(复杂度极值nlogn),并用kruskal在nlogn下求得,但是实现起来太麻烦了。。。

所以一般用一个比较简单的方法--分块。

将sqrt(n)区间内的点分在一块当中,分为sqrt(n)块,按区间排序。以左端点所在块内为第一关键字,右端点为第二关键字,进行排序,也就是以(pos[l],r)进行排序,然后复杂度就保证是O(nlogn)了。。。以下为证明。。。。

一、i与i+1在同一块内,r单调递增,所以r是O(n)的。由于有n^0.5块,所以这一部分时间复杂度是n^1.5。
二、i与i+1跨越一块,r最多变化n,由于有n^0.5块,所以这一部分时间复杂度是n^1.5
三、i与i+1在同一块内时变化不超过n^0.5,跨越一块也不会超过2*n^0.5,不妨看作是n^0.5。由于有n个数,所以时间复杂度是n^1.5
于是就变成了O(n^1.5)了

以下为代码:

试了一下,如果不加分块的话必定超时,加了之后就是187ms,吓cry。。。。

#include #define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
const int maxn = 100005;
int n,m,a[maxn],ppos[maxn];
long long ans[maxn];
int v1[maxn][33],v2[maxn][33],v3[maxn][33],v4[maxn][33];
int size1[maxn],size2[maxn];
struct Q{
int l,r,id;
bool operator <(const Q & b)const{
if(ppos[l] == ppos[b.l])return r < b.r;
return ppos[l] < ppos[b.l];
}
void read(int i){scanf("%d%d",&l,&r);id = i;}
}q[maxn];
int gcd(int a,int b){return !b ? a : gcd(b,a % b);}
int pool[50],pos[50],cnt;
void unique(int &cnt)
{
int id = 0,p = pos[0];
for(int i = 0;i < cnt;i++)
{
if(pool[i] != pool[id]){
pos[id] = p;id++;p = pos[i];pool[id] = pool[i];
}
}
pos[id] = p;
cnt = id + 1;
}
void init()
{
cnt = 0;
for(int i = n;i >= 1;i--)
{
for(int j = 0;j < cnt;j++)pool[j] = gcd(pool[j],a[i]);
pool[cnt] = a[i];pos[cnt++] = i;
unique(cnt);
for(int j = cnt - 1;j >= 0;j--)
{
v1[i][cnt - 1 - j] = pool[j];
v2[i][cnt - 1 - j] = pos[j];
}
size1[i] = cnt;
}
cnt = 0;
for(int i = 1;i <= n;i++)
{
for(int j = 0;j < cnt;j++)pool[j] = gcd(pool[j],a[i]);
pool[cnt] = a[i];pos[cnt++] = i;
unique(cnt);
for(int j = cnt - 1;j >= 0;j--)
{
v3[i][cnt - 1 - j] = pool[j];
v4[i][cnt - 1 - j] = pos[j];
}
size2[i] = cnt;
}
}
int l,r;
ll sum;
void add_l(int v)
{
int s = l,t = r;
ll temp = 0;
int last = s;
for(int i = 0;i < size1[l];i++){
if(v2[l][i] < s)continue;
else if(v2[l][i] > t)
temp += (t - last + 1) * 1LL * v1[l][i];
else {
temp += (v2[l][i] - last + 1) * 1LL * v1[l][i];
last = v2[l][i] + 1;
}
if(v2[l][i] >= t)break;
}
sum += v * temp;
}
void add_r(int v)
{
int s = l,t = r;
ll temp = 0;
int last = t;
for(int i = 0;i < size2[r];i++){
if(v4[r][i] > t)continue;
else if(v4[r][i] < s)
temp += (last - s + 1) * 1LL * v3[r][i];
else {
temp += (last - v4[r][i] + 1) * 1LL * v3[r][i];
last = v4[r][i] - 1;
}
if(v4[t][i] <= s)break;
}
sum += v * temp;
}
int main()
{
int T;
scanf("%d",&T);
for(int cas = 1;cas <= T;cas++)
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)scanf("%d",a + i);
for(int i = 1;i <= n;i++)
ppos[i] = (i - 1) / 100;
init();
scanf("%d",&m);
for(int i = 0;i < m;i++)q[i].read(i);
sort(q,q + m);
sum = 0,l = 1,r = 0;
for(int i = 0;i < m;i++)
{
if(r < q[i].r){
for(r = r + 1;r <= q[i].r;r++)
add_r(1);
r--;
}
if(r > q[i].r){
for(;r > q[i].r;r--)
add_r(-1);
}
if(l > q[i].l){
for(l = l - 1;l >= q[i].l;l--)
add_l(1);
l++;
}
if(l < q[i].l){
for(;l < q[i].l;l++)
add_l(-1);
}
ans[q[i].id] = sum;
}
for(int i = 0;i < m;i++)
printf("%I64d\n",ans[i]);
}
}

hdu 5381 2015多校第八场 莫队算法相关推荐

  1. [HDU](6333)Problem B. Harvest of Apples ---- 数论+莫队算法

    Problem Description There are n apples on a tree, numbered from 1 to n. Count the number of ways to ...

  2. 2022杭电多校第八场题解

    2022杭电多校第八场 Theramore(思维) 题意 给定一个01字符串,每次可以将一个奇数长度的区间翻转,求操作后字典序最小的字符串. 分析 翻转奇数长度的区间,元素位置的奇偶性不变,统计奇数位 ...

  3. 2021牛客暑假多校第八场 K题—Yet Another Problem About Pi

    2021牛客暑假多校第八场 K题-Yet Another Problem About Pi 题意:告诉你一个单元格的长和宽,问你走Π(3.1415926-)的长度距离最多可以走几个单元格 思路:沿着单 ...

  4. hdu 4358(莫队算法+dfs序列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 解题思路:用dfs求出整棵树的dfs序列,这样以u为根节点的子树就转化到相对应的区间上了.由于是 ...

  5. hdu 5213(容斥原理+莫队算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5213 莫队算法是离线处理一类区间不修改查询类问题的算法.就是如果你知道了[L,R]的答案.你可以在O( ...

  6. 2021杭电多校第八场补题

    比赛传送门:Contest Problem List (hdu.edu.cn) 1006)GCD Game 题目翻译:爱丽丝和鲍勃正在玩游戏. 他们轮流操作.有n个数字,a1,a2,...,an.每次 ...

  7. HDU多校1 - 6959 zoto(莫队+树状数组/值域分块)

    题目链接:点击查看 题目大意:在二维平面内有 nnn 个点,表示为 (i,f[i])(i,f[i])(i,f[i]),需要回答 mmm 次询问,每次询问会给出一个矩形,问矩形内有多少个不同的 yyy ...

  8. hdu 5317 RGCDQ (2015多校第三场第2题)素数打表+前缀和相减求后缀(DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5317 题意:F(x) 表示x的不同质因子的个数结果是求L,R区间中最大的gcd( F(i) , F(j ...

  9. 2015多校第9场 HDU 5405 Sometimes Naive 树链剖分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5405 题意: 给你一棵n个节点的树,有点权.        要求支持两种操作: 操作1:更改某个节点的 ...

最新文章

  1. IBM Installation Manager 工具概述(转)
  2. 开学季:当当大促的额外优惠又来啦!150 买 400的书!搓搓搓~
  3. wxWidgets:wxCmdLineParser类用法
  4. android BufferedOutputStream的使用
  5. CF908G New Year and Original Order 数位DP
  6. 【blockly教程】第五章 循环结构
  7. 《101 Windows Phone 7 Apps》读书笔记-ALARM CLOCK
  8. 最值钱的程序员打法 机器学习从入门到精通50篇+自学python全套教程!
  9. 十大开源安全测试工具
  10. win10 linux efi分区大小,EFI模式 win10+Ubuntu16.04双系统
  11. Linux Wps 缺少字体
  12. Verilog语言乒乓球机8段译码器
  13. 用妙记多 Mojidoc 实践康奈尔笔记法
  14. 能力素质有所欠缺_表达能力至关重要
  15. MySQL存储引擎MyISAM和InnoDB的区别
  16. 低碳存储助力数字化建设,富士胶片磁带存储整体方案亮相2022数博会
  17. 手机客户端设置同济邮箱的方法
  18. 六度短网址服务平台原理
  19. 计算机3d 游戏制作,揭秘3D电影、游戏角色的制作过程!
  20. 【DASH】低延迟流式传输和新算法

热门文章

  1. 计算机系统总线功能组,计算机组到成原理(华科版)第六章 系统总线.ppt
  2. NVIDIA 显卡算力 统计表
  3. Python实战 | 如何抓取tx短片弹幕并作词云图分析
  4. 计算机在英语口语教学中的应用,计算机在英语口语与听力教学中的应用.doc
  5. 格式工厂的另类用法:视频下载、视频剪辑、动图GIF、屏幕录像
  6. QT Debugging Helper Missing
  7. Android一段时间无操作之后,进入广告轮播界面,以及触摸之后停止轮播
  8. Ubuntu16.04安装谷歌浏览器和selenium
  9. Python一键下载1000张惊艳的微信头像
  10. PhpStudy的安装及使用教程