The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 641    Accepted Submission(s): 277

Problem Description
 You have an array A with the length of $n$
\[Let\quad f(l,r) = \sum_{i = l}^{r}\sum_{j = i}^{r}\quad gcd(a_{i},a_{i+1},\dots,a_{j})\]
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers $n$
Second line has $n$ integers $A_i$
Third line has one integers $Q$ the number of questions
Next there are $Q$ lines,each line has two integers $l,r$
$1 \leq T  \leq 3$
$1 \leq n,Q \leq 10^4$
$1 \leq a_i \leq 10^9$
$1\leq l,r \leq n$
 
Output
For each question,you need to print $f(l,r)$
 
Sample Input
2
5
1 2 3 4 5
3
1 3
2 3
1 4
4
4 2 6 9
3
1 3
2 4
2 3
 
Sample Output
9
6
16
18
23
10
 
Author
SXYZ
 
Source
 
解题:线段树,学习了一位大神的写法,原来区间是可以这样子合并,本菜表示涨姿势了,again
 
先说说区间的合并吧,$gcd(gcd(1,2) gcd(3,4)) = gcd(1,4)$
 
我们先模拟下 四个数范围比较小的情况
 
1L:(11) 1R:(11)
2L:(22) 2R:(22)
3L:(33) 3R:(33)
4L:(44) 4R:(44)
 
1与2 合并 3与4合并
12L:(11,12) 12R:(22,12)
34L:(33,34) 34R:(44,34)
 
12 与 34 合并
1234L:(11,12,13,14)
1234R:(44,34,24,14)
非常巧妙。。。赞
每个R的最后一个都代表着整个区间
而且每个R的里面的区间最右边都是区间的最右边
所以左子树的右区间 与有子树的右区间是可以合并的
因为左子树的右区间都是以右子树的最左-1结尾的
 
同理 左区间合并。
 
至于数量的计算,上面说gcd的时候已经说了
 
另外,可能会有相同的gcd,所以用Ln Rn来记录相同gcd的出现次数
 
还有随着区间的增长,gcd不会变大,只会不变或者变得更小
 
 
 #include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = ;
struct node {
LL sum;
int Lg[],Rg[],Ln[],Rn[],Lc,Rc;
} tree[maxn<<];
node pushup(const node &a,const node &b) {
node ret;
ret.sum = a.sum + b.sum;
for(int i = ; i < a.Rc; ++i)
for(int j = ; j < b.Lc; ++j)
ret.sum += __gcd(a.Rg[i],b.Lg[j])*1LL*a.Rn[i]*b.Ln[j];
for(int i = ; i < b.Rc; ++i) {
ret.Rg[i] = b.Rg[i];
ret.Rn[i] = b.Rn[i];
}
for(int i = ; i < a.Lc; ++i) {
ret.Lg[i] = a.Lg[i];
ret.Ln[i] = a.Ln[i];
}
int d = b.Rg[b.Rc-],p = b.Rc;
for(int i = ; i < a.Rc; ++i) {
int tmp = __gcd(a.Rg[i],d);
if(tmp == ret.Rg[p-]) ret.Rn[p-] += a.Rn[i];
else {
ret.Rg[p] = tmp;
ret.Rn[p++] = a.Rn[i];
}
}
ret.Rc = p;
d = a.Lg[a.Lc-],p = a.Lc;
for(int i = ; i < b.Lc; ++i) {
int tmp = __gcd(d,b.Lg[i]);
if(tmp == ret.Lg[p-]) ret.Ln[p-] += b.Ln[i];
else {
ret.Ln[p] = b.Ln[i];
ret.Lg[p++] = tmp;
}
}
ret.Lc = p;
return ret;
}
void build(int L,int R,int v) {
if(L == R) {
tree[v].Lc = tree[v].Rc = ;
tree[v].Ln[] = tree[v].Rn[] = ;
scanf("%d",&tree[v].Lg[]);
tree[v].sum = tree[v].Rg[] = tree[v].Lg[];
return;
}
int mid = (L + R)>>;
build(L,mid,v<<);
build(mid+,R,v<<|);
tree[v] = pushup(tree[v<<],tree[v<<|]);
}
void query(int L,int R,int lt,int rt,int v) {
if(lt <= L && rt >= R) {
if(lt == L) tree[] = tree[v];
else tree[] = pushup(tree[],tree[v]);
return;
}
int mid = (L + R)>>;
if(lt <= mid) query(L,mid,lt,rt,v<<);
if(rt > mid) query(mid+,R,lt,rt,v<<|);
}
int main() {
int kase,n,m,x,y;
scanf("%d",&kase);
while(kase--) {
scanf("%d",&n);
build(,n,);
scanf("%d",&m);
while(m--) {
scanf("%d%d",&x,&y);
query(,n,x,y,);
printf("%I64d\n",tree[].sum);
}
}
return ;
}

2015 Multi-University Training Contest 8 hdu 5381 The sum of gcd的更多相关文章

  1. hdu 5381 The sum of gcd(线段树+gcd)

    题目链接:hdu 5381 The sum of gcd 将查询离线处理,依照r排序,然后从左向右处理每一个A[i],碰到查询时处理.用线段树维护.每一个节点表示从[l,i]中以l为起始的区间gcd总 ...

  2. hdu 5381 The sum of gcd 2015多校联合训练赛#8莫队算法

    The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) T ...

  3. hdu 5381 The sum of gcd 莫队+预处理

    The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) P ...

  4. hdu 5381 The sum of gcd

    知道对于一个数列,如果以x为左(右)端点,往右走,则最多会有log(a[x])个不同的gcd,并且有递减性 所以会分成log段,每一段的gcd相同 那我们可以预处理出对于每一个位置,以这个位置为左端点 ...

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

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

  6. 2015 Multi-University Training Contest 8 hdu 5390 tree

    tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...

  7. 2015 Multi-University Training Contest 8 hdu 5383 Yu-Gi-Oh!

    Yu-Gi-Oh! Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID:  ...

  8. 2015 Multi-University Training Contest 8 hdu 5385 The path

    The path Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: 5 ...

  9. 2015 Multi-University Training Contest 3 hdu 5324 Boring Class

    Boring Class Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

随机推荐

  1. JS经常使用表单验证总结

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  2. linux下的oom调试笔记【原创】

    平台信息:内核:linux3.0.68 系统:android/android5.1平台:s5p4418 作者:庄泽彬(欢迎转载,请注明作者) 邮箱:2760715357@qq.com 摘要:调整and ...

  3. nyoj--79--导弹拦截(动态规划)

    拦截导弹 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任 ...

  4. css中!important的用法

    {*rule !important}这个css规则当今在网页制作的时候的普及已经非常流行了,以前我对它的理解就停留在‘浏览器是否识别阶段’ 而没有真正去研究过,可是现在发生了变化.众所周知,!impo ...

  5. 【React Natvie】React-native-swiper的安装和配置【ES6】

    react-native-swiper轮播图,是我们开发中特别常见的效果,首先感谢编写react-native-swiper的大神,让我们方便了很多.这个框架主要是用来做轮播图,焦点图等,内置了各种样 ...

  6. TYVJ 1427 线段树的基本操作

    题意: 单点修改,区间最值 思路: 线段树 原题请戳这里 //By SiriusRen #include <cstdio> #include <cstring> #includ ...

  7. 在Mac OSX上安装ffmpeg && ffmpeg命令行将h264封装为mp4

    ffmpeg功能强大,可以通过命令行来对音视频进行处理.为了使用其功能,我在Mac上对其进行了安装. 我的Mac OS X 系统版本:OS X Yosemite, 10.10.14 关于ffmpeg在 ...

  8. 根据项目类型导入Excel文件到不同数据库

    前提:如果您要针对不同的业务做数据导入,可以参考下这个项目,这个项目的原理就是根据文件名进行区分,然后导入不同的数据表.下面我就写个Demo演示下: 学生表-- 主键,学生姓名,学生年龄,学校归属 教 ...

  9. 使用新的CSS类型对象模型

    el.attributeStyleMap.set('padding', CSS.px(42)); const padding = el.attributeStyleMap.get('padding') ...

  10. Android学习——碎片Fragment的使用

    一.碎片的简单用法(实现在一个活动中添加两个碎片,并让这两个碎片平分活动空间) 1.新建一个FragmentTest项目: 新建一个左侧碎片布局left_fragment.xml,代码如下:(只放置一 ...