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. Gamma阶段测试计划

    前言 点击这一链接访问公课网(笨拙软件工程组). 一.Alpha阶段场景测试 1.1 鹿丸:无欲无求大三学生 保研无望 不在乎给分 只想选择干货多的课程 充实自己 需求和目标:了解各专业课程的授课内容 ...

  2. mui 文件上传注意问题

    1. mui 文件上传 key对应后台接收参数名,但对对于多文件上传就没办法了,addFile 的key不能重复 task.addFile( "_www/a.doc", {key: ...

  3. ASP.Net 知识点总结(五)

    1.传入某个属性的set方法的隐含参数的名称是什么?value,它的类型和属性所声名的类型相同.2.如何在C#中实现继承? 在类名后加上一个冒号,再加上基类的名称.3.C#支持多重继承么? 不支持.可 ...

  4. [TYVJ1391]走廊泼水节

    Description 话说,中中带领的OIER们打算举行一次冬季泼水节,当然这是要秘密进行的,绝对不可以让中中知道.不过中中可是老江湖了,当然很快就发现了我们的小阴谋,于是他准备好水枪迫不及待的想要 ...

  5. 页面置换算法-LRU(Least Recently Used)c++实现

    最近最久未使用(LRU)置换算法 #include <iostream> #include <cstdio> #include <cstring> #include ...

  6. Eclipse里的Java EE视图在哪里?MyEclipse里的Java EE视图在哪里?MyEclipse里的MyEclipse Java Enterprise视图在哪里?(图文详解)

    为什么要写这篇博客呢? 是因为,最近接触一个web项目. 然后呢,Eclipse里的Java EE视图的位置与MyEclipse里不太一样.为了自己梳理日后查找,也是为了新手少走弯路. Eclipse ...

  7. oracle性能优化培训总结

  8. Python 设计模式--策略模式

    策略模式(Strategy Pattern) 策略模式是一种与行为相关的设计模式,允许你在运行时根据指定的上下文确定程序的动作.可以在两个类中封装不同的算法,并且在程序运行时确定到底执行哪中策略. 特 ...

  9. BPI-MI1刷Andorid的启动卡之后上网的步骤(以太网&&WIFI)

    BPI-MI1刷Andorid的启动卡之后上网的步骤(以太网&&WIFI) 2017/9/19 16:57 01刷Android的默认启动界面.png 02打开英文模式下的设置Sett ...

  10. Android Error:Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List;'.

    问题:Error:Unable to find method 'com.android.build.gradle.api.BaseVariant.getOutputs()Ljava/util/List ...