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. [深入理解Android卷一全文-第七章]深入理解Audio系统

    由于<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该由于纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容. ...

  2. objective-c 中数据类型之四 字典(NSDictionary)

    // 1. 字典初始化.赋值方式1 NSMutableDictionary *m_dictionary = [[NSMutableDictionary alloc] initWithCapacity: ...

  3. Zookeeper体系结构

    上面我们已经讨论了zookeeper在应用程序中的一些操作,以下我们须要理解一下服务端的工作的原理.client是怎样通过一个client的类库与服务端进行通信的,然后服务端又是怎样回应client的 ...

  4. nginx源代码分析--进程间通信机制 &amp; 同步机制

    Nginx源代码分析-进程间通信机制 从nginx的进程模型能够知道.master进程和worker进程须要通信,nginx中通信的方式有套接字.共享内存.信号.对于master进程,从外部接受信号, ...

  5. Visual C++ RunTime的特征——非烫即屯

    Visual C++ RunTime的特征——非烫即屯 大一刚学C语言,第二次上机课,当我发现我照着书抄写的程序在运行之外的黑框里面跳出一排“烫烫烫烫烫”,当时就震惊了.你们能想象一个来自小城,在大学 ...

  6. bzoj1833: [ZJOI2010]count 数字计数(数位DP+记忆化搜索)

    1833: [ZJOI2010]count 数字计数 题目:传送门 题解: 今天是躲不开各种恶心DP了??? %爆靖大佬啊!!! 据说是数位DP裸题...emmm学吧学吧 感觉记忆化搜索特别强: 定义 ...

  7. <% %> in html

    $(document).on('click', '.invoiceNumber', function () { var string = <%= StaticHelper.GetCurrentC ...

  8. TensorRT加速 ——NVIDIA终端AI芯片加速用,可以直接利用caffe或TensorFlow生成的模型来predict(inference)

    官网:https://developer.nvidia.com/tensorrt 作用:NVIDIA TensorRT™ is a high-performance deep learning inf ...

  9. Django中的session和cookie及分页设置

    cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...

  10. FTP协议讲解

    FTP 概述 文件传输协议(FTP)作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用.FTP的目标是提高文件的共享性和可靠高效地传送数据. 在传输文件时,FTP 客户端程序先与服务器建立连接 ...