Codeforces 672E:Ultimate Weirdness of an Array 线段树

E. Ultimate Weirdness of an Array
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 0gcd(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!

Input

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.

Output

Print a single line containing the value of ultimate weirdness of the array a.

Example
input
3
2 6 3
output
6
Note

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.
Thus the answer is  3 + 0 + 0 + 1 + 0 + 2 = 6.

题意是求所有区间[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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值