CodeForces 671C - Ultimate Weirdness of an Array
题意:
给以一个定义, F(l, r) 的值表示序列 A[1:n]的子序列
A[1....(l-1),(r+1)...n] 之中 任意两个数的最大公约数的最大值。
求 Sum=∑i=1N∑j=1N(F(i,j)),(i≠j)
思路:
英文题解
大致解释一下:
H[i] 表示 F(l, r) <= i 区间 (l,r) 的个数。
V[A[i]] = { b1, b2, .... bk }, 其中 A[i] % bx == 0
还有一个next 数组
设 next[j] = k, 表示 F(l, k) <= i, k 尽可能的小。
当然会有 k 不存在的时候, 则 next[j] = n+1;(为什么, 看下面)
这时候可以知道 :
H[i]=∑j=1N(n−next[j]+1)
右端为 next[j] , 左端则有 n-next[j]+1种选择。
Code:
#include <bits/stdc++.h>
#define lson l , m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std;
typedef long long LL;
const LL maxn = 200000 + 131;
const LL MaxN = 200000;
struct node {
LL Max, Min;
LL Sum, Flag;
};
node Node[maxn<<2];
LL H[maxn], A[maxn], Idx[maxn];
LL L1[maxn], L2[maxn], R1[maxn], R2[maxn];
///SegmentTree
void PushUp(LL rt) {
Node[rt].Max = max(Node[rt<<1].Max, Node[rt<<1|1].Max);
Node[rt].Min = min(Node[rt<<1].Min, Node[rt<<1|1].Min);
Node[rt].Sum = Node[rt<<1].Sum + Node[rt<<1|1].Sum;
}
void PushDown(LL l, LL r, LL rt) {
LL m = (l + r) >> 1;
if(Node[rt].Flag)
{
Node[rt<<1].Flag = Node[rt<<1].Max = Node[rt<<1].Min = Node[rt].Flag;
Node[rt<<1|1].Flag = Node[rt<<1|1].Max = Node[rt<<1|1].Min = Node[rt].Flag;
Node[rt<<1].Sum = Node[rt].Flag * (m - l + 1);
Node[rt<<1|1].Sum = Node[rt].Flag * (r - m);
Node[rt].Flag = 0;
}
}
void Build(LL l, LL r, LL rt) {
Node[rt].Flag = 0;
if(l == r) {
Node[rt].Max = Node[rt].Min = Node[rt].Sum = l;
return ;
}
LL m = (l + r) >> 1;
Build(lson), Build(rson);
PushUp(rt);
}
void Update_section(LL L, LL R, LL val, LL l, LL r, LL rt) {
if(L > R) return ;
if(Node[rt].Min >= val) return ;
if(L <= l and r <= R and Node[rt].Max <= val) {
Node[rt].Flag = val;
Node[rt].Min = Node[rt].Max = val;
Node[rt].Sum = LL(r - l + 1) * LL(val);
return ;
}
PushDown(l, r, rt);
LL m = (l + r) >> 1;
if(L <= m) Update_section(L, R, val, lson);
if(R > m) Update_section(L, R, val, rson);
PushUp(rt);
}
/// Solve
int main() {
std::ios::sync_with_stdio(false);
LL n;
cin >> n;
for(LL i = 1; i <= n; ++i) {
cin >> A[i];
Idx[A[i]] = i;
}
/// Get l(1, b1) -> bk-1, (b1,b2) -> bk, (b2, n) -> n+1
for(LL i = 1; i <= MaxN; ++i)
{
for(LL j = i; j <= MaxN; j +=i)
if(Idx[j])
{
if(L1[i] == 0 or L1[i] > Idx[j]) L2[i] = L1[i], L1[i] = Idx[j];
else if(L2[i] == 0 or L2[i] > Idx[j]) L2[i] = Idx[j];
if(R1[i] < Idx[j]) R2[i] = R1[i], R1[i] = Idx[j];
else if(R2[i] < Idx[j]) R2[i] = Idx[j];
}
}
/// Build Tree
Build(1,n,1);
for(LL i = MaxN; i > 0; --i)
{
if(L1[i] != R1[i])
{
Update_section(1,L1[i],R2[i], 1, n, 1);
Update_section(L1[i]+1, L2[i], R1[i], 1, n, 1);
Update_section(L2[i]+1, n, n+1, 1, n, 1);
}
H[i] = LL(n*(n+1)) - Node[1].Sum;
//cout << H[i] << endl;
}
LL Ans = 0;
for(LL i = 1; i < MaxN; ++i)
Ans += i * (H[i+1]-H[i]);
cout << Ans <<endl;
return 0;
}
CodeForces 671C - Ultimate Weirdness of an Array的更多相关文章
- Codeforces 671C - Ultimate Weirdness of an Array(线段树维护+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 *2800 的 DS,不过还是被我自己想出来了 u1s1 这个 D1C 比某些 D1D 不知道难到什么地方去了 首先碰到这类问题我们肯定考 ...
- codeforces 671C Ultimate Weirdness of an Array 线段树+构造
题解上说的很清楚了,我照着写的,表示膜拜题解 然后时间复杂度我觉得应该是O(nlogn),虽然常数略大,预处理和倒着扫,都是O(nlogn) #include <stdio.h> #inc ...
- Codeforces 671C. Ultimate Weirdness of an Array(数论+线段树)
看见$a_i\leq 200000$和gcd,就大概知道是要枚举gcd也就是答案了... 因为答案是max,可以发现我们很容易算出<=i的答案,但是很难求出单个i的答案,所以我们可以运用差分的思 ...
- 【CodeForces】671 C. Ultimate Weirdness of an Array
[题目]C. Ultimate Weirdness of an Array [题意]给定长度为n的正整数序列,定义一个序列的价值为max(gcd(ai,aj)),1<=i<j<=n, ...
- Ultimate Weirdness of an Array CodeForces - 671C (gcd,线段树)
大意: 定义一个数列的特征值为两个数gcd的最大值, $f(l,r)$表示数列删除区间$[l,r]$的元素后剩余元素的特征值, 求$\sum_{i=1}^n\sum_{j=i}^n{f(i,j)}$ ...
- CF671C. Ultimate Weirdness of an Array
n<=200000个<=200000的数问所有的f(i,j)的和,表示去掉区间i到j后的剩余的数字中任选两个数的最大gcd. 数论日常不会.. 先试着计算一个数组:Hi表示f(l,r)&l ...
- Codeforces 221d D. Little Elephant and Array
二次联通门 : Codeforces 221d D. Little Elephant and Array /* Codeforces 221d D. Little Elephant and Array ...
- Codeforces Round #181 (Div. 2) A. Array 构造
A. Array 题目连接: http://www.codeforces.com/contest/300/problem/A Description Vitaly has an array of n ...
- Codeforces Round #284 (Div. 1) C. Array and Operations 二分图最大匹配
题目链接: http://codeforces.com/problemset/problem/498/C C. Array and Operations time limit per test1 se ...
随机推荐
- MongoDB系列:四、spring整合mongodb,带用户验证
在前面的两篇博客 MongoDB常用操作练习.springboot整合mongoDB的简单demo中,我们基本上熟悉了mongodb,也把它与spring boot进行了整合并且简单使用.在本篇博客中 ...
- 为App添加Log日志文件
using System; using System.Globalization; using System.IO; using System.Text; using System.Windows.F ...
- 定时任务调度工作(学习记录 四)schedule与scheduleAtFixedRate的区别
根据两种情况来看区别 一.首次计划执行的时间早于当前的时间 1.schedule方法 “fixed-delay”:如果第一次执行时间被延迟了,随后的执行时间按照上一次实际执行完成的时间点进行计算 演示 ...
- BigDecimal(大浮点数)
因为这个单词,和他的四则运算方法总是记不住,所以写入博客,在没有印象的时候再看看自己的博客. BigDecimal的加减乘除不和double float 一样,他需要使用方法来进行加减乘除. 加法:a ...
- MySQL之B+树索引(转自掘金小册 MySQL是怎样运行的,版权归作者所有!)
每个索引都对应一棵B+树,B+树分为好多层,最下边一层是叶子节点,其余的是内节点.所有用户记录都存储在B+树的叶子节点,所有目录项记录都存储在内节点. InnoDB存储引擎会自动为主键(如果没有它会自 ...
- C++编程音视频库ffmpeg的pts时间换算方法
ffmpeg中的pts,dts,duration时间记录都是基于timebase换算,我们主要分析下pts的时间怎么换算,其它的是一样的换算.ffmpeg的时间换算对许多新接触同学算是一个大坑,很多刚 ...
- 【CSA72G】【XSY3316】rectangle 线段树 最小生成树
题目大意 有一个 \(n\times n\) 的矩阵 \(A\).最开始 \(A\) 中每个元素的值都为 \(0\). 有 \(m\) 次操作,每次给你 \(x_1,x_2,y_1,y_2,w\),对 ...
- python: c_char_p指向的bitmap图像数据,通过c_char_Array最终赋值给PIL的Image对象
def GetCurrentImage(self): ok, bitmap, buff_len = self.GetCurrentFrameBitmap() #调用C函数,返回位图数据的指针. bit ...
- Go package(1) time 用法
golang使用的版本: go version go1.10.3 一:功能介绍 time的一些功能,比如时区,像linux中的定时器,时间计算等 格式化时间 时区(Location) 时间计算 Tic ...
- Hbase 客户端Scan
Hbase 客户端Scan 标签(空格分隔): Hbase HBase扫描操作Scan 1 介绍 扫描操作的使用和get()方法类似.同样,和其他函数类似,这里也提供了Scan类.但是由于扫描工作方式 ...