题意:http://acm.hdu.edu.cn/showproblem.php?pid=5381

思路:这个题属于没有修改的区间查询问题,可以用莫队算法来做。首先预处理出每个点以它为起点向左和向右连续一段的gcd发生变化的每个位置,不难发现对每个点A[i],这样的位置最多logA[i]个,这可以利用ST表用nlognlogA[i]的时间预处理,然后用二分+RMQ在nlogn的时间内得到。然后就是区间变化为1时的转移了,不难发现区间变化为1时,变化的答案仅仅是以变化的那一个点作为左端点或右端点的连续子串的gcd的和,而这个gcd最多logA[i]种,利用前面的预处理可以在logA[i]的时间内累加得到答案。总复杂度O(NlogNlogA[i]+N√NlogA[i])

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull; //#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?:-;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0);
const int INF = 1e9 + ;
const double EPS = 1e-8; /* -------------------------------------------------------------------------------- */ const int maxn = 1e4 + ; int gcd(int a, int b) {
return b? gcd(b, a % b) : a;
} struct ST {
int dp[maxn][];
int index[maxn];
void init_index() {
index[] = ;
for (int i = ; i < maxn; i ++) {
index[i] = index[i - ];
if (!(i & (i - ))) index[i] ++;
}
}
void init_gcd(int a[], int n) {
for (int i = ; i < n; i ++) dp[i][] = a[i];
for (int j = ; ( << j) <= n; j ++) {
for (int i = ; i + ( << j) - < n; i ++) {
dp[i][j] = gcd(dp[i][j - ], dp[i + ( << (j - ))][j - ]);
}
}
} int query_gcd(int L, int R) {
int p = index[R - L + ];
return gcd(dp[L][p], dp[R - ( << p) + ][p]);
}
};
ST st; int n, q, block;
int a[maxn];
vector<int> L[maxn], R[maxn];
pair<pii, int> b[maxn]; bool cmp(const pair<pii, int> &a, const pair<pii, int> &b) {
int lb = a.X.X / block, rb = b.X.X / block;
return lb == rb? a.X.Y < b.X.Y : lb < rb;
} void init() {
for (int i = ; i < n; i ++) {
L[i].clear();
R[i].clear();
}
for (int i = ; i < n; i ++) {
int u = i;
R[i].pb(i - );
while (u < n) {
int l = u, r = n - ;
while (l < r) {
int m = (l + r + ) >> ;
if (st.query_gcd(i, m) == st.query_gcd(i, u)) l = m;
else r = m - ;
}
u = l + ;
R[i].pb(l);
}
}
for (int i = ; i < n; i ++) {
int u = i;
L[i].pb(i + );
while (u >= ) {
int l = , r = u;
while (l < r) {
int m = (l + r) >> ;
if (st.query_gcd(m, i) == st.query_gcd(u, i)) r = m;
else l = m + ;
}
u = l - ;
L[i].pb(l);
}
}
} ll f(int l, int r) {
ll ans = ;
for (int i = ; i < R[l].size(); i ++) {
if (r <= R[l][i]) return ans + (ll)(r - R[l][i - ]) * st.query_gcd(l, r);
ans += (ll)(R[l][i] - R[l][i - ]) * st.query_gcd(l, R[l][i]);
}
} ll g(int l, int r) {
ll ans = ;
for (int i = ; i < L[r].size(); i ++) {
if (l >= L[r][i]) return ans + (ll)(L[r][i - ] - l) * st.query_gcd(l, r);
ans += (ll)(L[r][i - ] - L[r][i]) * st.query_gcd(L[r][i], r);
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T;
cin >> T;
st.init_index();
while (T --) {
cin >> n;
block = (int)sqrt(n + 0.1);
for (int i = ; i < n; i ++) {
scanf("%d", a + i);
}
st.init_gcd(a, n);
init();
cin >> q;
for (int i = ; i < q; i ++) {
scanf("%d%d", &b[i].X.X, &b[i].X.Y);
b[i].X.X --;
b[i].X.Y --;
b[i].Y = i;
}
sort(b, b + q, cmp);
vector<ll> ans(q);
ll lastans = a[];
int lastl = , lastr = ;
/** 注意区间变化的顺序,优先考虑扩大区间,保证任何时刻区间不为负 */
for (int i = ; i < q; i ++) {
while (lastl > b[i].X.X) {
lastl --;
lastans += f(lastl, lastr);
}
while (lastr < b[i].X.Y) {
lastr ++;
lastans += g(lastl, lastr);
}
while (lastl < b[i].X.X) {
lastans -= f(lastl, lastr);
lastl ++;
}
while (lastr > b[i].X.Y) {
lastans -= g(lastl, lastr);
lastr --;
}
ans[b[i].Y] = lastans;
}
for (int i = ; i < q; i ++) {
printf("%I64d\n", ans[i]);
}
}
return ;
}

hdu5381 The sum of gcd]莫队算法的更多相关文章

  1. HDOJ 5381 The sum of gcd 莫队算法

    大神题解: http://blog.csdn.net/u014800748/article/details/47680899 The sum of gcd Time Limit: 2000/1000 ...

  2. HDU-4676 Sum Of Gcd 莫队+欧拉函数

    题意:给定一个11~nn的全排列AA,若干个询问,每次询问给出一个区间[l,r][l,r],要求得出∑l≤i<j≤r  gcd(Ai,Aj)的值. 解法:这题似乎做的人不是很多,蒟蒻当然不会做只 ...

  3. Hdu5381-The sum of gcd(莫队)

    题意我就不说了   解析: 莫队,先预处理出以i为右端点的区间的gcd值,有一些连续的区间的gcd值是相同的,比如[j,i],[j+1,i],[j+2,i]的gcd值是相同的,我们可以把[j,j+2] ...

  4. 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 ...

  5. hdu 4676 Sum Of Gcd 莫队+phi反演

    Sum Of Gcd 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4676 Description Given you a sequence of ...

  6. hdu 4676 Sum Of Gcd 莫队+数论

    题目链接 给n个数, m个询问, 每个询问给出[l, r], 问你对于任意i, j.gcd(a[i], a[j]) L <= i < j <= R的和. 假设两个数的公约数有b1, ...

  7. HDU5381【莫队算法+区间GCD特性】

    前言: 主要最近在刷莫队的题,这题GCD的特性让我对莫队的使用也有了新的想法.给福利:神犇的一套莫队算法题 先撇开题目,光说裸的一个莫队算法,主要的复杂度就是n*sqrt(n)对吧,这里我忽略了一个左 ...

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

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

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

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

随机推荐

  1. 阿里面试官让我实现一个线程安全并且可以设置过期时间的LRU缓存,我蒙了!

    目录 1. LRU 缓存介绍 2. ConcurrentLinkedQueue简单介绍 3. ReadWriteLock简单介绍 4.ScheduledExecutorService 简单介绍 5. ...

  2. gitbook命令

    安装gitbook命令 前提:已经安装nodejs npm install -g gitbook-cli 查看版本号 gitbook -V gitbook命令 gitbook -h Usage: gi ...

  3. 泛微ecology OA系统在数据库配置信息泄露

    漏洞描述 攻击者可通过该漏洞页面直接获取到数据库配置信息,攻击者可通过访问存在漏洞的页面并解密从而获取数据库配置信息,如攻击者可直接访问数据库,则可直接获取用户数据,由于泛微e-cology默认数据库 ...

  4. jdbc-手写Java方法连接数据库

    一.关键四元素   ①    com.mysql.jdbc.Driver      mysql数据库连接jar包.   获取途径: 链接:https://pan.baidu.com/s/1SFcjuu ...

  5. XSS语义分析的阶段性总结(二)

    本文首发于“合天智汇”微信公众号,作者:Kale 前言 上次分享了javascript语义分析,并且简单介绍了新型xss扫描器的一些想法,如何在不进行大量fuzz的情况下又能准确的检测出xss漏洞,这 ...

  6. BUAA_OO 第二单元总结

    作业分析 第一次作业 本次作业是单次可捎带电梯的设计,主要是初步了解多线程的设计实现和测试,本身算法设计非常简单.这次作业整体来说不是很难,是多线程的入门,主要目的就是让我们认识,了解一下什么是多线程 ...

  7. sql语句-------重复时插入更新

    ON DUPLICATE KEY UPDATE重复时插入更新 insert into user(id,username) value('231',"二人") on duplicat ...

  8. 2019-2020-1 20199303《Linux内核原理与分析》第七周作业

    进程的描述 1.进程概念 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位.进程由程序段.数据段.PCB组成 2.PCB中的信息 ①进程标识符 ②处理机状态 ③进程调度信息 ④进程控制 ...

  9. (二)PL/SQL特殊符号

    PL/SQL标识符 PL/SQL标识符是常量,变量,异常,过程,游标和保留字.标识符是由一个字母后面可以跟更多的字母,数字,美元符号,下划线和数字符号,并且不得超过30个字符. 默认情况下,标识符不区 ...

  10. docker-数据管理(3)

    Docker 容器中管理数据主要有两种方式: 数据卷(Data volumes) 数据卷容器(Data volumes containers 数据卷是一个可供一个或者多个容器使用的特殊目录,它绕过UF ...