Codeforces 671C. Ultimate Weirdness of an Array(数论+线段树)
看见$a_i\leq 200000$和gcd,就大概知道是要枚举gcd也就是答案了...
因为答案是max,可以发现我们很容易算出<=i的答案,但是很难求出单个i的答案,所以我们可以运用差分的思想。
$H[i]$表示$f(l,r)<=i$的$(l,r)$对数,显然这个是随i增大而单调不降的,考虑怎么计算出这个。
$next[l]$表示满足$f(l,r)<=i$的最小的$r$,则有$H[i]=\sum_{l=1}^{n}n-next[l]+1$。显然$next[l]$也会随着$i$变小而单调不降,并且$next$数组本身也是单调不降的,于是我们可以从大到小枚举$i$。$i=max(a[i])$的时候显然有$next[i]=i$,接下来只要考虑每次从$i$变成$i-1$的时候$next$数组怎么变化。
用一个vector $v[i]$来存下约数里有$i$的数的下标,并且单调递增。设$v[i]$里有下标$x_1,x_2,x_3,...,x_m$,则从$i$变为$i-1$的时候,任何一个$[l,r]$至少包含$m-1$个$x_j$,所以$[x_2+1,n]$这段区间的$next[l]$应该全改为$n+1$,$[x_1+1,x_2]$这段区间的$next[l]$应该改为$max(next[l],x_m)$,$[1,x_1]$这段区间的$next[l]$应该改为$max(next[l],x_{m-1})$,这个可以用线段树来实现。
怎么实现呢?刚才我们提到过$next[l]$单调不降,有了这个性质就很好实现了。
每个节点维护$mn$和$mx$表示这个区间里的最小的$next$和最大的$next$,如果$mn \geq delta$,那就不用再递归这个区间了,如果$mx<delta$,那么直接给这个区间打标记,这么做就能找到需要改的区间了。
然后求出$H[i]$就完了...
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=;
struct poi{int mx, mn, delta; ll sum;}tree[maxn<<];
int n, a[maxn], pos[maxn], mx;
ll ans, H[maxn];
vector<int>v[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void change(int x, int l, int r, int delta)
{
tree[x].mn=tree[x].mx=delta;
tree[x].sum=1ll*(r-l+)*delta;
tree[x].delta=delta;
}
inline void up(int x)
{
tree[x].mn=min(tree[x<<].mn, tree[x<<|].mn);
tree[x].mx=max(tree[x<<].mx, tree[x<<|].mx);
tree[x].sum=tree[x<<].sum+tree[x<<|].sum;
}
inline void down(int x, int l, int r)
{
if(!tree[x].delta) return;
int mid=(l+r)>>;
change(x<<, l, mid, tree[x].delta);
change(x<<|, mid+, r, tree[x].delta);
tree[x].delta=;
}
void build(int x, int l, int r)
{
if(l==r) {tree[x].mn=tree[x].mx=tree[x].sum=l; return;}
int mid=(l+r)>>;
build(x<<, l, mid); build(x<<|, mid+, r);
up(x);
}
void update(int x, int l, int r, int cl, int cr, int delta)
{
if(tree[x].mn>=delta) return;
down(x, l, r);
if(cl<=l && r<=cr && tree[x].mx<delta) {change(x, l, r, delta); return;}
int mid=(l+r)>>;
if(cl<=mid) update(x<<, l, mid, cl, cr, delta);
if(cr>mid) update(x<<|, mid+, r, cl, cr, delta);
up(x);
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(a[i]), pos[a[i]]=i, mx=max(mx, a[i]);
for(int i=;i<=mx;i++)
{
for(int j=i;j<=mx;j+=i)
if(pos[j]) v[i].push_back(pos[j]);
sort(v[i].begin(), v[i].end());
}
build(, , n);
for(int i=mx;~i;i--)
{
H[i]=1ll*n*n-tree[].sum+n;
int m=v[i].size();
if(m<=) continue;
update(, , n, v[i][]+, n, n+);
update(, , n, v[i][]+, v[i][], v[i][m-]);
update(, , n, , v[i][], v[i][m-]);
}
for(int i=;i<=mx;i++) ans+=1ll*i*(H[i]-H[i-]);
printf("%I64d\n", ans);
}
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
题意: 给以一个定义, F(l, r) 的值表示序列 A[1:n]的子序列 A[1....(l-1),(r+1)...n] 之中 任意两个数的最大公约数的最大值. 求 Sum=∑i=1N∑j=1N(F ...
- CodeForces Round #179 (295A) - Greg and Array 一个线段树做两次用
线段树的区间更新与区间求和...一颗这样的线段树用两次... 先扫描1~k...用线段树统计出每个操作执行的次数... 那么每个操作就变成了 op. l , op.r , op.c= times* ...
- 【CodeForces】671 C. Ultimate Weirdness of an Array
[题目]C. Ultimate Weirdness of an Array [题意]给定长度为n的正整数序列,定义一个序列的价值为max(gcd(ai,aj)),1<=i<j<=n, ...
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- CF671C. Ultimate Weirdness of an Array
n<=200000个<=200000的数问所有的f(i,j)的和,表示去掉区间i到j后的剩余的数字中任选两个数的最大gcd. 数论日常不会.. 先试着计算一个数组:Hi表示f(l,r)&l ...
- codeforces 482B. Interesting Array【线段树区间更新】
题目:codeforces 482B. Interesting Array 题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val. 就是区间l---r上的与的值为val,最后问你原来的数 ...
- codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...
随机推荐
- JMeter学习笔记(二) 一些实际应用的基础操作
我在CSDN上面找到一位大师整理的jmeter性能测试基础,分享到这里继续学习 https://blog.csdn.net/u011541946/article/category/6893578/1
- 虚拟货币——比特币行情价格分析
最近挖以太币的朋友们在关注以太坊行情时,一定会发现以太币的价格对比之前上涨了不少.肯定有部分朋友想了解这次上涨的原因,我们特地为此查询了一番.因为比特币相当于虚拟货币中的黄金,它的价格波动会波及到其他 ...
- Mybatis-Plus的填坑之路 - Lynwood/wunian7yulian
目录 Mybatis-Plus 我来填坑~ 目录 一.简单介绍 官方说明 : 成绩: 最新版本: 开发层面MyBatis-Plus特色 Mybatis-Plus中的Plus 二.MP的特性 三.MP框 ...
- libCurl 初步认识 - cur easy
cur easy接口简洁明了,主接口4个,辅接口5个. 主接口 初始化 + 配参数 + 执行 + 销毁 初始化 CURL* curl_easy_init() 获得CURL句柄,返回值需要判空. 配参数 ...
- 微软职位内部推荐-Principal Development Lead - SharePoint
微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...
- 软银集团和共享办公空间公司WeWork在日本成立合资公司
[TechWeb报道]7月18日消息,据国外媒体报道,软银集团和共享办公空间公司WeWork联合宣布,在日本成立合资公司WeWork Japan. 该合资公司将在日本开设联合办公空间,于明年初在东京设 ...
- 下载android sdk更新包离线安装解决方案
本文转载自:http://xljboox.blog.163.com/blog/static/7628448320111159354738/ 第一次安装android sdk后进行开发包的更新,你应该了 ...
- 15 分钟用 ML 破解一个验证码系统
人人都恨验证码——那些恼人的图片,显示着你在登陆某网站前得输入的文本.设计验证码的目的是,通过验证你是真实的人来避免电脑自动填充表格.但是随着深度学习和计算机视觉的兴起,现在验证码常常易被攻破. 我拜 ...
- Codeforces Round #613 Div.1 D.Kingdom and its Cities 贪心+虚树
题目链接:http://codeforces.com/contest/613/problem/D 题意概述: 给出一棵树,每次询问一些点,计算最少删除几个点可以让询问的点两两不连通,无解输出-1.保证 ...
- USACO 2.4.4 Bessie Come Home 回家(最短路)
Description 现在是晚餐时间,而母牛们在外面分散的牧场中. 农民约翰按响了电铃,所以她们开始向谷仓走去. 你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只速度最快 ...