前言:

主要最近在刷莫队的题,这题GCD的特性让我对莫队的使用也有了新的想法。给福利:神犇的一套莫队算法题

先撇开题目,光说裸的一个莫队算法,主要的复杂度就是n*sqrt(n)对吧,这里我忽略了一个左端点(增加/删除)或者右端点(增加/删除)的所带来的复杂度,

之前也遇到过卡这里的复杂度,但是是因为简单的long long计算多而造成了复杂度增大,从而转变一下。

回到这道题:给出区间,求所有子区间的gcd和。

思路:

莫队算法+gcd的特性。

外面就是套了一个莫队,排序然后离散化操作优化了复杂度得n*sqrt(n)。

然后呢?我们要去计算一个右结点的增加或删除的贡献。

先预处理所有区间之间的gcd,利用ST表。

在这里:当一个右端点的删除/增加

问题就是:如何快速求所有存在这个右端的子区间的GCD的贡献。

这里利用的是区间gcd的特性,一段区间上不同的gcd最多只有logn个。

对于右端点:

预处理右端点固定,不同gcd的区间段的GCD(直接枚举,更新位置,由于一段区间GCD的gcd个数不会超过logn,所以最多会预处理logn段不同的gcd段),并且预处理右端固定的不同gcd段的最远位置(用二分就行,因为GCD会随着区间大而变小,当前区间最小即最大),所以每次查询时间要乘以logn;

对于左端点同理;

总的复杂度:O(n*sqrt(n)*log(n))。

代码还有一些简要注释可以参考。

这个代码打不出来...就多打打!练手!23333333333

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e4+10;
int a[N],n,m;
vector<PII>VL[N];
vector<PII>VR[N];
int pos[N];
struct asd{
int left,right,id;
LL res;
};
asd S[N];
bool cmp(asd x,asd y)
{
if(pos[x.left]==pos[y.left]) return x.right<y.right;
return pos[x.left]<pos[y.left];
} //RMQ预处理,以某个端点为起点向一个方向延伸的区间的gcd的最远延伸的方向和对应的gcd
//Rmq[i][j]表示第 i 个数起,连续 2^j 个数的GCD;
int Rmq[N][15];
void GetRmq()
{
for(int i=1; i<=n; i++)
Rmq[i][0]=a[i];
for(int i=1; (1<<i)<=n; i++)
for(int j=1; j<=n; j++)
if(j+(1<<i)-1<=n)
Rmq[j][i]=__gcd(Rmq[j][i-1],Rmq[j+(1<<(i-1))][i-1]);
}
int query(int L, int R)
{
int k=(int)log2(R-L+1);
return __gcd(Rmq[L][k],Rmq[R-(1<<k)+1][k]);
}
//固定s为右端点,向左延伸gcd为t的最远位置
int Rsearch(int s,int L,int R,int t)
{
int ans;
while(L<=R)
{
int mid=(L+R)>>1;
if(query(mid,s)==t)
{
ans=mid;
R=mid-1;
}
else L=mid+1;
}
return ans;
}
//固定s为左端点,向右延伸gcd为t的最远位置
int Lsearch(int s,int L,int R,int t)
{
int ans;
while(L<=R)
{
int mid=(L+R)>>1;
if(query(s,mid)==t)
{
ans=mid;
L=mid+1;
}
else R=mid-1;
}
return ans;
}
//计算s为右端点的贡献,t 为当前区间左端点
LL Rcal(int s,int t)
{
LL ans=0;
int ss=s;
for(int i=0;i<VR[s].size();i++)
{
ans+=(1LL*(ss-max(t,VR[s][i].second)+1)*VR[s][i].first);
ss=VR[s][i].second-1;
if(ss<t) break;
}
return ans;
}
//计算s为左端点的贡献,t 为当前区间右端点
LL Lcal(int s,int t)
{
LL ans=0;
int ss=s;
for(int i=0;i<VL[s].size();i++)
{
ans+=(1LL*(min(t,VL[s][i].second)-ss+1)*VL[s][i].first);
ss=VL[s][i].second+1;
if(ss>t) break;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int block=(int)sqrt(n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/block+1;
}
GetRmq(); //预处理左端 i 固定的不同gcd区间段
for(int i=1;i<=n;i++)
{
int r=i;
VL[i].clear();
while(r<=n)
{
int ant=query(i,r);
r=Lsearch(i,r,n,ant);
VL[i].push_back(make_pair(ant,r));
r++;
}
}
//预处理右端 i 固定的不同gcd区间段
for(int i=n;i>=1;i--)
{
int l=i;
VR[i].clear();
while(l>=1)
{
int ant=query(l,i);
l=Rsearch(i,1,l,ant);
VR[i].push_back(make_pair(ant,l));
l--;
}
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&S[i].left,&S[i].right);
S[i].id=i;
}
sort(S,S+m,cmp);
LL sum=0;
int l=0,r=1;
for(int i=0;i<m;i++)
{
while(r<=S[i].right)
{
sum+=Rcal(r,l+1);
r++;
}
while(r>S[i].right+1)
{
r--;
sum-=Rcal(r,l+1);
}
while(l<S[i].left-1)
{
l++;
sum-=Lcal(l,r-1);
}
while(l>=S[i].left)
{
sum+=Lcal(l,r-1);
l--;
}
S[S[i].id].res=sum;
}
for(int i=0;i<m;i++)
printf("%lld\n",S[i].res);
}
return 0;
}

HDU5381【莫队算法+区间GCD特性】的更多相关文章

  1. hdu5381 The sum of gcd]莫队算法

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=5381 思路:这个题属于没有修改的区间查询问题,可以用莫队算法来做.首先预处理出每个点以它为起点向左和向右连 ...

  2. HDU 5381 The sum of gcd (技巧,莫队算法)

    题意:有一个含n个元素的序列,接下来有q个询问区间,对每个询问区间输出其 f(L,R) 值. 思路: 天真单纯地以为是道超级水题,不管多少个询问,计算量顶多就是O(n2) ,就是暴力穷举每个区间,再直 ...

  3. D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

    D. Powerful array time limit per test seconds memory limit per test megabytes input standard input o ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  5. Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...

  6. 莫队算法 2038: [2009国家集训队]小Z的袜子(hose)

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 ...

  7. BZOJ-2038 小Z的袜子(hose) 莫队算法

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec Memory Limit: 259 MB Submit: 5573 Solved: 2568 [Subm ...

  8. 【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)(组合计数+概率+莫队算法+分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2038 学了下莫队,挺神的orzzzz 首先推公式的话很简单吧... 看的题解是从http://for ...

  9. bzoj 2038 莫队算法

    莫队算法,具体的可以看10年莫涛的论文. 大题思路就是假设对于区间l,r我们有了一个答案,那么对于区间l,r+1,我们 可以暴力的转移一个答案,那么对于区间l1,r1和区间l2,r2,需要暴力处理 的 ...

随机推荐

  1. OpenGLES 与 WebGL 中顶点属性的组织格式的误解 - 一个不好笑的笑话

    版权声明:本文为博主原创文章,未经博主同意不得转载.转载联系 QQ 30952589.加好友请注明来意. https://blog.csdn.net/sleks/article/details/289 ...

  2. crm高速开发之EntityCollection

    /* 创建者:菜刀居士的博客  * 创建日期:2014年07月07号  */ namespace Net.CRM.OrganizationService {     using System;     ...

  3. 关于JavaScript中prototype机制的理解

    最近几天一直在研究JavaScript中原型的机制,从开始的似懂非懂,到今天终于有所领悟.不敢说彻底理解,但是起码算知道怎么回事了. 为什么一开始似懂非懂 开始了解一遍原型机制后,感觉知其然但不知其所 ...

  4. 模拟登陆,selenium,线程池

    一 . 模拟登陆案例(识别验证码)  1 . 打码平台 - 云打码 : www.yundama.com  使用步骤 : - 注册两个账户,普通用户和开发者用户 : - 登陆 普通用户查看余额 登陆开发 ...

  5. 深入浅出,JS原型链的工作原理

    前言:原型链,即原型链条.它是由原型.原型的原型.原型的原型的原型...这一规则组合成的,经常被应用于继承. 原型的作用在JS中,每个对象都有自己的原型.当我们访问对象的属性和方法时,JS会先访问对象 ...

  6. latex 技巧汇总

    最近打算详细的学习一下latex,所以在学习的过程中遇到了一些问题.随时出问题,随时记录更新. 我是萌萌的Latex, x_0. 再写具体的技巧之前,先说一个关于打公式的小技巧.有时候你不知道怎么设置 ...

  7. BZOJ 3043 IncDec Sequence:反向差分

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3043 题意: 给定一个长度为n的数列a[i],每次可以选择一个区间[l,r],使这个区间内 ...

  8. BZOJ 1616 [Usaco2008 Mar]Cow Travelling游荡的奶牛:dp【网格型】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1616 题意: 有一个n*m的网格. '.'表示平坦的草地,'*'表示挡路的树(不能走). ...

  9. js正则表达式(2)

    找到以某个字符串开头的字符串 var myReg=/^(abc)/gim; 如果不加m,那么只找一行,而加了m可以找到每行中以该字符串开头的匹配文本. 如: abcsfsdfasd7890hklfah ...

  10. storm源码剖析(1):storm脚本

    今天看了一下storm的命令行脚本${STORM_HOME}/bin/storm,现在将剖析过程整理一下,作为记录.注:使用的storm版本为0.8.0. ${STORM_HOME}/bin/stor ...