您的位置:首页 > 其它

HDU 5381 The sum of gcd 莫队算法

2016-09-23 17:48 369 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5381

题意:给定一个数组,每次询问给出l和r,求出























































 

思路:看的大牛的代码,心累

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#define debug() puts("here")
using namespace std;

typedef long long ll;
const int N = 10010;
struct node
{
int l, r, id;
} g
;
int n, m, unit;
ll res
, tmp;
int a
, b
, c
;
struct vv
{
int id, g;
};
vector<vv> vec1
, vec2
;
int gcd(int a, int b)
{
return !b ? a : gcd(b, a % b);
}
bool cmp(node a, node b)
{
return a.l/unit != b.l/unit ? a.l/unit < b.l/unit : a.r < b.r;
}
void work()
{
for(int i = 1; i <= n; i++) vec1[i].clear(), vec2[i].clear();
for(int i = 1; i <= n; i++)
{
if(i == 1) vec1[i].push_back(vv{i, a[i]});
else
{
int curg = a[i], id = i;
for(auto &it : vec1[i-1])
{
int g = gcd(curg, it.g);
if(g != curg) vec1[i].push_back(vv{id, curg});
curg = g, id = it.id;
}
vec1[i].push_back(vv{id, curg});
}
}
for(int i = n; i >= 1; i--)
{
if(i == n) vec2[i].push_back(vv{i, a[i]});
else
{
int curg = a[i], id = i;
for(auto &it : vec2[i+1])
{
int g = gcd(curg, it.g);
if(g != curg) vec2[i].push_back(vv{id, curg});
curg = g, id = it.id;
}
vec2[i].push_back(vv{id, curg});
}
}
}
ll calr(int l, int r)
{
ll sum = 0;
int tr = r;
for(auto &it : vec1[r])
if(it.id >= l)
{
sum += (ll)(tr - it.id + 1) * it.g;
tr = it.id - 1;
}
else
{
sum += (ll)(tr - l + 1) * it.g;
break;
}
return sum;
}
ll call(int l, int r)
{
ll sum = 0;
int tl = l;
for(auto &it : vec2[l])
if(it.id <= r)
{
sum += (ll)(it.id - tl + 1) * it.g;
tl = it.id + 1;
}
else
{
sum += (ll)(r - tl + 1) * it.g;
break;
}
return sum;
}
void solve()
{
unit = (int)sqrt(1.0 * n);
sort(g+1, g+1+m, cmp);
int l = 1, r = 0;
tmp = 0;
for(int i = 1; i <= m; i++)
{
while(r < g[i].r) tmp += calr(l, ++r);
while(r > g[i].r) tmp -= calr(l, r--);
while(l < g[i].l) tmp -= call(l++, r);
while(l > g[i].l) tmp += call(--l, r);
res[g[i].id] = tmp;
}
for(int i = 1; i <= m; i++) printf("%lld\n", res[i]);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d%d", &g[i].l, &g[i].r), g[i].id = i;
work();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: