Yasin has an array a containing n integers. Yasin is a 5 year old, so he loves ultimate weird things.
Yasin denotes weirdness of an array as maximum gcd(ai, aj) value among all 1 ≤ i < j ≤ n. For n ≤ 1 weirdness is equal to 0, gcd(x, y) is the greatest common divisor of integers x and y.
He also defines the ultimate weirdness of an array. Ultimate weirdness is where f(i, j) is weirdness of the new array a obtained by removing all elements between i and j inclusive, so new array is[a1... ai - 1, aj + 1... an].
Since 5 year old boys can't code, Yasin asks for your help to find the value of ultimate weirdness of the given array a!
The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of elements in a.
The next line contains n integers ai (1 ≤ ai ≤ 200 000), where the i-th number is equal to the i-th element of the array a. It is guaranteed that all ai are distinct.
Print a single line containing the value of ultimate weirdness of the array a.
3 2 6 3
6
Consider the first sample.
- f(1, 1) is equal to 3.
- f(2, 2) is equal to 1.
- f(3, 3) is equal to 2.
- f(1, 2), f(1, 3) and f(2, 3) are equal to 0.
题意是求所有区间[i,j],f(i,j)的和。f(i,j)表示除去i,j的区间之外的数其中两个最大的gcd。
这题想了很久很久,看题解看了很久很久。。。
ai是从1到200000的数,对于每一个i维护一个区间h(j,k),h(j,k)的含义是f(j,k)<=i,对于每一个j,找最小的k。
然后对于i来说的话,gcd<=i的区间数目就可以枚举j,对每一个j算相应的k值,也就是题解中的next[j]值。sum(n-next[j]+1) (1<=j<=n)
可以发现就是找能够整除这个数的最左距离,次左距离,次右距离,最右距离。
之后就是使用线段树更新这个和了。
代码:
#pragma warning(disable:4996)
#include <fstream>
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x33ffffff
#define mem(a, b) memset(a, b, sizeof(a))
#define pper(i,n,m) for(int i = n;i >= m; i--)
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
#define mp make_pair
#define ff first
#define ss second
#define pb push_back
const int maxn = 200005;
const ll mod = 1e9 + 7;
const double PI = acos(-1.0);
struct no
{
ll maxx;
ll minn;
ll sum;
ll flag;
}node[maxn * 4];
void pushup(int root)
{
node[root].maxx = max(node[root << 1].maxx, node[(root << 1)| 1].maxx);
node[root].minn = min(node[root << 1].minn, node[(root << 1) | 1].minn);
node[root].sum = node[root << 1].sum + node[(root << 1) | 1].sum;
}
void pushdown(int root, int le, int ri)
{
int mid = (le + ri) >> 1;
if (node[root].flag)
{
node[root << 1].flag = node[root << 1].maxx = node[root << 1].minn = node[root].flag;
node[(root << 1) | 1].flag = node[(root << 1) | 1].maxx = node[(root << 1) | 1].minn = node[root].flag;
node[root << 1].sum = node[root << 1].flag*(mid - le + 1);
node[(root << 1) | 1].sum = node[(root << 1) | 1].flag*(ri - mid);
node[root].flag = 0;
}
}
void build(int root, int le, int ri)
{
node[root].flag = 0;
if (le == ri)
{
node[root].maxx = node[root].minn = node[root].sum = le;
return;
}
int mid = (le + ri) >> 1;
build(root << 1, le, mid);
build((root << 1) | 1, mid + 1, ri);
pushup(root);
}
void update(int oper_le, int oper_ri, int val, int le, int ri, int root)
{
if (oper_le > oper_ri)
return;
if (node[root].minn >= val)
return;
if (oper_le <= le&&ri <= oper_ri&&node[root].maxx <= val)
{
node[root].flag = node[root].maxx = node[root].minn = val;
node[root].sum = ll(ri - le + 1)*val;
return;
}
pushdown(root, le, ri);
int mid = (le + ri) >> 1;
if (oper_le <= mid)
{
update(oper_le, oper_ri, val, le, mid, root << 1);
}
if (oper_ri > mid)
{
update(oper_le, oper_ri, val, mid + 1, ri, (root << 1) | 1);
}
pushup(root);
}
int n;
ll val[maxn], ans[maxn], id[maxn], le1[maxn], le2[maxn], ri1[maxn], ri2[maxn];
void solve()
{
int i, j, k;
sa(n);
memset(id, 0, sizeof(id));
repp(i, 1, n)
{
sa(val[i]);
id[val[i]] = i;
}
for (i = 1; i <= 200000; i++)
{
for (j = i; j <= 200000; j += i)
{
if (id[j])
{
if (le1[i] == 0 || id[j] < le1[i])
{
le2[i] = le1[i];
le1[i] = id[j];
}
else if (le2[i] == 0 || id[j] < le2[i])
{
le2[i] = id[j];
}
if (ri1[i] == 0 || id[j] > ri1[i])
{
ri2[i] = ri1[i];
ri1[i] = id[j];
}
else if (ri2[i] == 0 || id[j] > ri2[i])
{
ri2[i] = id[j];
}
}
}
}
build(1, 1, n);
for (i = 200000; i >= 1; i--)
{
if (le1[i] != ri1[i])
{
update(1, le1[i], ri2[i], 1, n, 1);
update(le1[i] + 1, le2[i], ri1[i], 1, n, 1);
update(le2[i] + 1, n, n + 1, 1, n, 1);
}
ans[i] = 1LL*n*(n + 1) - node[1].sum;
}
ll res = 0;
for (i = 200000 - 1; i >= 1; i--)
{
res = res + 1LL*(ans[i + 1] - ans[i])*i;
}
printf("%I64d", res);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif
solve();
return 0;
}