n<=200000个<=200000的数问所有的f(i,j)的和,表示去掉区间i到j后的剩余的数字中任选两个数的最大gcd。

数论日常不会。。

先试着计算一个数组:Hi表示f(l,r)<=i的(l,r)的数量。这样答案就是i*(H_i - H_i-1)的和。要求删掉某个区间后剩余的区间的最大gcd,暴力一点,从大到小枚举gcd的值,然后对每个数记Next_i表示如果当前的gcd为<=x,以i节点做l,r能取到的最小值,那么一个gcd值x的H_x就是一个x对应的所有n-Next_i+1的和。

这样要n^2,问题在于没有考虑Next数组的特点。可以发现对每个x,Next数组是不递减的,而从大到小枚举x只会使限制越来越紧,然后使Next_i越来越大,如果能够在x变成x-1时做一些相应的修改就可以节省每次重算Next的时间。

假设一个x的所有倍数的下标是b1,b2,……,b_k,那么当x变成x-1后,[l,r]至少应覆盖k-1个数,所以i>b2时所有的i都要设成n+1表示对后面的H不再有贡献。b1<i<=b2时,至少要覆盖到bk,所以这些Next_i对bk取个Max,然后1<=i<=b1时,Next_i对b_(k-1)取个Max,完成一次修改。每次取H[x]只需要知道所有Next的和。

需要一个线段树。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<math.h>
#include<vector>
//#include<iostream>
using namespace std; int n;
#define maxn 200011
#define LL long long
int a[maxn];
vector<int> s[maxn]; int prime[maxn],lp=,xiao[maxn];bool notprime[maxn];
void pre(int n)
{
for (int i=;i<=n;i++)
{
if (!notprime[i]) prime[++lp]=i,xiao[i]=i;
for (int j=;j<=lp && 1ll*i*prime[j]<=n;j++)
{
xiao[i*prime[j]]=prime[j];
notprime[i*prime[j]]=;
if (!(i%prime[j])) break;
}
}
} int sep[maxn],lsep,numofsep[maxn];
void dfs(int cur,int num,int idx)
{
if (cur>lsep) {s[num].push_back(idx);return;}
dfs(cur+,num,idx);
for (int i=,tmp=sep[cur];i<=numofsep[cur];i++,tmp*=sep[cur]) dfs(cur+,num*tmp,idx);
} struct SMT
{
struct Node
{
int ls,rs;
LL sum,be,Max,Min;
}a[maxn<<];
int size;
SMT() {size=;}
void up(int x)
{
const int &p=a[x].ls,&q=a[x].rs;
a[x].sum=a[p].sum+a[q].sum;
a[x].Max=max(a[p].Max,a[q].Max);
a[x].Min=min(a[p].Min,a[q].Min);
}
void build(int &x,int L,int R)
{
x=++size;
if (L==R) {a[x].ls=a[x].rs=; a[x].sum=a[x].Min=a[x].Max=L; a[x].be=; return;}
const int mid=(L+R)>>;
build(a[x].ls,L,mid); build(a[x].rs,mid+,R); up(x);
}
void build() {int x;build(x,,n);}
int ql,qr; LL v;
void modmaxsingle(int x,int L,int R,LL v)
{
a[x].sum=(R-L+)*v;
a[x].Max=a[x].Min=v;
a[x].be=v;
}
void down(int x,int L,int R)
{
const int &p=a[x].ls,&q=a[x].rs,mid=(L+R)>>;
if (a[x].be) {modmaxsingle(p,L,mid,a[x].be); modmaxsingle(q,mid+,R,a[x].be); a[x].be=;}
}
void Modmax(int x,int L,int R)
{
if (a[x].Min>=v) return;
if (ql<=L && R<=qr && a[x].Max<=v)
{
modmaxsingle(x,L,R,v);
return;
}
down(x,L,R);
const int mid=(L+R)>>;
if (ql<=mid) Modmax(a[x].ls,L,mid);
if (qr> mid) Modmax(a[x].rs,mid+,R);
up(x);
}
void modmax(int L,int R,LL v)
{
ql=L; qr=R; this->v=v;
Modmax(,,n);
}
}t; LL h[maxn];
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
pre();
for (int i=;i<=n;i++)
{
int tmp=a[i];
lsep=;
while (tmp>)
{
if (sep[lsep]!=xiao[tmp]) sep[++lsep]=xiao[tmp],numofsep[lsep]=;
else numofsep[lsep]++;
tmp/=xiao[tmp];
}
dfs(,,i);
}
t.build();
for (int g=;g;g--)
{
int size=s[g].size();
if (size>)
{
t.modmax(s[g][]+,n,n+);
t.modmax(s[g][]+,s[g][],s[g][size-]);
t.modmax(,s[g][],s[g][size-]);
}
h[g]=1ll*n*(n+)-t.a[].sum;
}
LL ans=;
for (int i=;i<=;i++) ans+=i*(h[i+]-h[i]);
printf("%lld\n",ans);
return ;
}

set也能写。不会。

CF671C. Ultimate Weirdness of an Array的更多相关文章

  1. 【CodeForces】671 C. Ultimate Weirdness of an Array

    [题目]C. Ultimate Weirdness of an Array [题意]给定长度为n的正整数序列,定义一个序列的价值为max(gcd(ai,aj)),1<=i<j<=n, ...

  2. codeforces 671C Ultimate Weirdness of an Array 线段树+构造

    题解上说的很清楚了,我照着写的,表示膜拜题解 然后时间复杂度我觉得应该是O(nlogn),虽然常数略大,预处理和倒着扫,都是O(nlogn) #include <stdio.h> #inc ...

  3. 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 ...

  4. 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)}$ ...

  5. Codeforces 671C. Ultimate Weirdness of an Array(数论+线段树)

    看见$a_i\leq 200000$和gcd,就大概知道是要枚举gcd也就是答案了... 因为答案是max,可以发现我们很容易算出<=i的答案,但是很难求出单个i的答案,所以我们可以运用差分的思 ...

  6. Codeforces 671C - Ultimate Weirdness of an Array(线段树维护+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 *2800 的 DS,不过还是被我自己想出来了 u1s1 这个 D1C 比某些 D1D 不知道难到什么地方去了 首先碰到这类问题我们肯定考 ...

  7. Segment Tree Beats 区间最值问题

    Segment Tree Beats 区间最值问题 线段树一类特殊技巧! 引出:CF671C Ultimate Weirdness of an Array 其实是考试题,改题的时候并不会区间取最值,区 ...

  8. CF上的3道小题(1)

    CF上的3道小题 终于调完了啊.... T1:CF702E Analysis of Pathes in Functional Graph 题意:你获得了一个n个点有向图,每个点只有一条出边.第i个点的 ...

  9. Codeforces Round #352 (Div. 2) ABCD

    Problems     # Name     A Summer Camp standard input/output 1 s, 256 MB    x3197 B Different is Good ...

随机推荐

  1. 自定义View(10)*onSizeChanged,onMeasure,onDraw的注意事项及正确写法

    1,onSizeChanged 触发: 当view的第一次分配大小或以后大小改变时的产生的事件. 工作: 计算绘制内容的位置,面积等相关值.避免每次在onDraw中计算了. 注意: 计算时不要忘记pa ...

  2. 381 Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复

    设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构.注意: 允许出现重复元素.    insert(val):向集合中插入元素 val.    remove(val):当 val ...

  3. 278 First Bad Version 第一个错误的版本

    你是产品经理,目前正在领导一个团队开发一个新产品.不幸的是,您的产品的最新版本没有通过质量检查.由于每个版本都是基于之前的版本开发的,所以错误版本之后的所有版本都是不好的.假设你有 n 个版本 [1, ...

  4. [转]oracle 同义词 synonym

    本文转自:http://blog.csdn.net/generalfu/article/details/7906561 同义词定义 当一个用户想访问另外一个用户的表时, 需要在表前加用户名,总加表名不 ...

  5. SqlServer知识点-操作xml

    一.开发环境 SQL2010 二.开发过程 1.声明一个xml类型变量 DECLARE @xmlInfo XML; SET @xmlInfo = '<CompanyGroup> <C ...

  6. 图标文件ico制作以及使用说明

    今天说一个图标文件——ico.我们在pc端浏览网页的时候网页栏那块都会显示一个本网站特有的图片,就是我们说的ico了.示例:<link href="image/favicon.ico& ...

  7. Elasticsearch--地理搜索

    目录 地理位置索引 空间搜索映射定义 示例 基于距离的排序 边界框过滤 距离的限制 任意地理形状搜索 点 包络线 多边形 多个多边形 把形状保存到索引中 地理位置索引 空间搜索映射定义 elastic ...

  8. python 模块-easygui.buttonbox

    2018-03-0315:43:11 ): Yes_or_No = easygui.buttonbox("是否良品?", choices=['Yes', 'No', '退出']) ...

  9. CommHelper

    18位流水号: public static string GenerateTransId(int i) { string transId = DateTime.Now.ToString("y ...

  10. HDU_1074_Doing Homework_状态压缩dp

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 Doing Homework Time Limit: 2000/1000 MS (Java/Othe ...