【题目】C. Ultimate Weirdness of an Array

【题意】给定长度为n的正整数序列,定义一个序列的价值为max(gcd(ai,aj)),1<=i<j<=n,定义f(i,j)为移除序列i~j后剩余序列的价值,求Σf(i,j)。1<=n,ai<=2*10^5。

【算法】数论+线段树

【题解】要求所有区间的f(i,j),转化为,记ans[i]表示f(l,r)=i的区间数量,则ANS=Σi*ans[i],i=1~mx,mx=max(ai)。

求解ans[i]不方便,记h[i]表示f(l,r)<=i的区间数量,则ans[i]=h[i]-h[i-1],显然h[i]单调不减。

考虑x=mx时,h[x]=n*(n+1)/2(即所有区间)。当x=mx-1时,设数列中mx的倍数有k个,就需要满足所选区间包含至少k-1个mx的倍数。随着x的减少,逐个将不满足的区间删除,就可以得到所有h[x]。

如何实现删除不满足的区间?

记v[i]表示数列中所有i的倍数的位置,用vector存储为v[i][k],这一步甚至可以用O(n√n)的分解素因数实现。

如果(l,r)合法,那么(l,R),R>r也一定合法。所以记next[i]表示L=i,R>=next[i]的区间均合法,初始next[i]=i。

对于x,h[x]=Σ(n-next[i]+1),i=1~n。

每次x减少,需要删除不满足x的区间时,假设x的倍数的位置为b1,b2……bk,需要进行以下3种操作:

1.p>b2,next[p]=n+1

2.b1<p<=b2,next[p]=max(next[p],bk)

3.1<=p<=b1,next[p]=max(next[p],bk-1)。

容易发现,next[i]是一个单调不减的数组,那么以上3个操作都可以用线段树的区间覆盖实现,答案用区间求和实现。(套路:线段树区间取max只能在单调的前提下通过区间覆盖实现

具体而言,线段树参数需要维护max,min,delta,sum,当min>=x时直接return,当max<=x时直接修改。

复杂度O(n log n)。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=;
struct tree{int l,r,mins,maxs,delta;ll sum;}t[maxn*];
int n,a[maxn];
ll h[maxn];
vector<int>v[maxn];
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
void up(int k){
t[k].sum=t[k<<].sum+t[k<<|].sum;
t[k].mins=min(t[k<<].mins,t[k<<|].mins);
t[k].maxs=max(t[k<<].maxs,t[k<<|].maxs);
}
void modify(int k,int x){t[k].delta=x;t[k].mins=t[k].maxs=x;t[k].sum=1ll*x*(t[k].r-t[k].l+);}
void down(int k){
if(t[k].delta){
modify(k<<,t[k].delta);
modify(k<<|,t[k].delta);
t[k].delta=;
}
}
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;t[k].delta=;
if(l==r){
t[k].maxs=t[k].mins=t[k].sum=l;
}
else{
int mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
up(k);
}
}
void fix(int k,int l,int r,int x){
if(l>r||t[k].mins>=x)return;
if(l<=t[k].l&&t[k].r<=r&&t[k].maxs<=x){modify(k,x);return;}
down(k);
int mid=(t[k].l+t[k].r)>>;
if(l<=mid)fix(k<<,l,r,x);
if(r>mid)fix(k<<|,l,r,x);
up(k);
}
int main(){
n=read();
int mx=;
for(int i=;i<=n;i++){
a[i]=read();
for(int j=;j*j<=a[i];j++)if(a[i]%j==){
v[j].push_back(i);
if(j*j!=a[i])v[a[i]/j].push_back(i);
}
mx=max(mx,a[i]);
}
build(,,n);
for(int i=mx+;i>=;i--){
if(v[i].size()>=){
fix(,v[i][]+,n,n+);
fix(,v[i][]+,v[i][],v[i][v[i].size()-]);
fix(,,v[i][],v[i][v[i].size()-]);
}
h[i]=1ll*n*(n+)-t[].sum;
}
ll ans=;
for(int i=;i<=mx;i++)ans+=1ll*(i-)*(h[i]-h[i-]);
printf("%lld",ans);
return ;
}

【CodeForces】671 C. Ultimate Weirdness of an Array的更多相关文章

  1. 【CodeForces】671 D. Roads in Yusland

    [题目]D. Roads in Yusland [题意]给定n个点的树,m条从下往上的链,每条链代价ci,求最少代价使得链覆盖所有边.n,m<=3*10^5,ci<=10^9,time=4 ...

  2. 【CodeForces】671 B. Robin Hood

    [题目]B. Robin Hood [题意]给定n个数字的序列和k次操作,每次将序列中最大的数-1,然后将序列中最小的数+1,求最终序列极差.n<=5*10^5,0<=k<=10^9 ...

  3. 【Codeforces】Round #491 (Div. 2) 总结

    [Codeforces]Round #491 (Div. 2) 总结 这次尴尬了,D题fst,E没有做出来.... 不过还好,rating只掉了30,总体来说比较不稳,下次加油 A:If at fir ...

  4. 【Codeforces】Round #488 (Div. 2) 总结

    [Codeforces]Round #488 (Div. 2) 总结 比较僵硬的一场,还是手速不够,但是作为正式成为竞赛生的第一场比赛还是比较圆满的,起码没有FST,A掉ABCD,总排82,怒涨rat ...

  5. 【LeetCode】153. Find Minimum in Rotated Sorted Array 解题报告(Python)

    [LeetCode]153. Find Minimum in Rotated Sorted Array 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode. ...

  6. 【LeetCode】154. Find Minimum in Rotated Sorted Array II 解题报告(Python)

    [LeetCode]154. Find Minimum in Rotated Sorted Array II 解题报告(Python) 标签: LeetCode 题目地址:https://leetco ...

  7. 【CodeForces】601 D. Acyclic Organic Compounds

    [题目]D. Acyclic Organic Compounds [题意]给定一棵带点权树,每个点有一个字符,定义一个结点的字符串数为往下延伸能得到的不重复字符串数,求min(点权+字符串数),n&l ...

  8. 【Codeforces】849D. Rooter's Song

    [算法]模拟 [题意]http://codeforces.com/contest/849/problem/D 给定n个点从x轴或y轴的位置p时间t出发,相遇后按对方路径走,问每个数字撞到墙的位置.(还 ...

  9. 【CodeForces】983 E. NN country 树上倍增+二维数点

    [题目]E. NN country [题意]给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖.\(n,m,q \leq 2*10^5\). [算法]树上倍增+二维数点(树状数组 ...

随机推荐

  1. lintcode-414-两个整数相除

    414-两个整数相除 将两个整数相除,要求不使用乘法.除法和 mod 运算符. 如果溢出,返回 2147483647 . 样例 给定被除数 = 100 ,除数 = 9,返回 11. 标签 二分法 思路 ...

  2. TCP系列43—拥塞控制—6、Congestion Window Validation(CWV)

    一.概述 在RFC2861中,区分了TCP连接数据传输的三种状态   After sending a data segment:       If tcpnow - T_last >= RTO ...

  3. winform 弹出窗体指定位置

    在启动一个程序时,我们希望窗口显示的位置处于屏幕的正中心,可以如下设置: MainForm mainForm = new MainForm(); mainForm.StartPosition = Fo ...

  4. 第114天:Ajax跨域请求解决方法(二)

    一.什么是跨域 我们先回顾一下域名地址的组成: http:// www . google : 8080 / script/jquery.js   http:// (协议号)       www  (子 ...

  5. 【ASP.NET 框架系列】您所经历的,但未必研究的那些技术

       本篇文章更适合具有一定开发经验,一定功底,且对底层代码有所研究的朋友!!! 本篇文章稍微偏原理且底层,有一定难度和且比较晦涩,文章粒度稍微粗些,更细粒度的,会在后续的文章中,结合具体的Demo实 ...

  6. 【.Net】从字符串数组中寻找数字的元素

    那是写一个类别来处理数字元素并收集起来. 开发程序,解决方法不是唯一的.相同的功能实现,方法不止一个. 参考下面代码: class Ak { private string[] _stringArray ...

  7. OSPF协议介绍及配置 (上)

    OSPF协议介绍及配置 (上) 一.OSPF概述 回顾一下距离矢量路由协议的工作原理:运行距离矢量路由协议的路由器周期性的泛洪自己的路由表,通过路由的交互,每台路由器都从相邻的路由器学习到路由,并且加 ...

  8. 【BZOJ3243】【NOI2013】向量内积(矩阵,数论)

    [BZOJ3243][NOI2013]向量内积(矩阵,数论) 题面 BZOJ 题解 这题好神仙. 首先\(60\)分直接是送的.加点随机之类的可以多得点分. 考虑正解. 我们先考虑一下暴力. 我们把\ ...

  9. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  10. bzoj3192: [JLOI2013]删除物品(树状数组)

    既然要从一个堆的堆顶按顺序拿出来放到第二个堆的堆顶,那么我们就可以把两个堆顶怼在一起,这样从一个堆拿到另一个堆只需要移动指针就好了. 换句话说,把1~n倒着,n+1到n+m正着,用一个指针把两个序列分 ...