Codeforces 题目传送门 & 洛谷题目传送门

*2800 的 DS,不过还是被我自己想出来了

u1s1 这个 D1C 比某些 D1D 不知道难到什么地方去了

首先碰到这类问题我们肯定考虑枚举什么东西,然后在枚举过程中用个什么东西维护答案,求出其对答案的贡献。此题一个很直观的想法是枚举左端点,但很遗憾此题涉及 gcd,不太好直接维护。故我们换个想法,枚举答案。

我们先预处理出每个数的所有因子——这个显然可以在 \(n\ln n\) 的时间内求出。然后从大到小动态地枚举一个指针 \(i\)。容易注意到的一件事情是如果 \(f(l,r)\geq i\),那么 \(f(l,r-1)\geq i\)。故考虑设 \(t_l\) 为以 \(l\) 为左端点的区间中,最小的满足 \(f(l,r)<i\) 的 \(r\)。那么显然满足 \(f(l,r)\geq i\) 的区间 \([l,r]\) 的个数为 \(\sum\limits_{i=1}^n(t_i-i)=\sum\limits_{i=1}^nt_i-\dfrac{n(n-1)}{2}\),而答案又显然可以用差分的思想转化为对于所有 \(i\),满足 \(f(l,r)\geq i\) 的区间 \([l,r]\) 的个数之和。

考虑当指针 \(i\) 从 \(i+1\) 变为 \(i\) 的时候会对 \(t_l\) 造成什么影响。显然只有满足 \(a_j\) 为 \(i\) 的倍数的位置 \(j\) 才有可能对 \(t_l\) 造成影响,故考虑将满足 \(a_j\) 是 \(i\) 的倍数的位置 \(j\) 按照下标从小到大排好,假设为 \(p_1,p_2,\dots,p_k\),那么有:

  • 若 \(k=1\),一个数显然不会对 \(t_l\) 产生任何影响,故不考虑 \(k=1\) 的情况。
  • 若 \(k>2\),那么:
    • 对于 \(l\in [1,x_1]\),\(\forall r\in[l,x_{m-1}-1]\),区间 \([l,r]\) 之外都有两个 \(i\) 的倍数(\(a_{x_{m-1}},a_{x_m}\)),故 \(t_l\leftarrow\max(t_l,x_{m-1})\)
    • 对于 \(l\in [x_1+1,x_2]\),\(\forall r\in[l,x_{m}-1]\),区间 \([l,r]\) 之外都有两个 \(i\) 的倍数(\(a_1,a_{x_m}\)),故 \(t_l\leftarrow\max(t_l,x_{m})\)
    • 对于 \(l\in [x_2+1,n]\),\(\forall r\in[l,n]\),区间 \([l,r]\) 之外都有两个 \(i\) 的倍数(\(a_1,a_2\)),故 \(t_l\leftarrow\max(t_l,n+1)\)

于是现在我们要实现支持区间取 \(\max\),全局求和的数据结构,这个显然是数据结构不太好直接维护的,第一篇题解说要这东西要用到什么吉司机线段树(反正我不会就对了)。不过我们静下心来好好想想,真的要这么麻烦吗?这个 \(t\) 数组就没有什么性质吗?不难发现,如果 \(f(l,r)\geq i\),那么 \(f(l+1,r)\geq i\)。故我们有 \(t_l\leq t_{l+1}\)。也就是说对于一次将 \(t_l,t_{l+1},t_{l+2},\dots,t_r\) 与 \(x\) 取 \(\max\) 的操作,我们显然可以找到一个断点 \(k\) 使得 \(t_l,t_{l+1},\dots,t_k\) 均小于 \(x\),\(t_{k+1},t_{k+2},\dots,t_r\) 均 \(\ge x\),故我们只需对 \([l,k]\) 进行区间赋值操作,这显然是普通线段树可以维护的。这个 \(k\) 可以通过线段树二分求出,二分出第一个 \(\geq x\) 的位置 \(p\) 并与 \(r+1\) 取 \(\min\),然后将区间 \([l,p-1]\) 赋上 \(x\) 即可。

时间复杂度 \(nd(a_i)+n\log n\)。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
const int MAX_ITEM=3e6;
int n,a[MAXN+5];vector<int> pos[MAXN+5];
struct chain_list{
int hd[MAXN+5],v[MAX_ITEM+5],nxt[MAX_ITEM+5],item_n=0;
void ins(int p,int q){v[++item_n]=q;nxt[item_n]=hd[p];hd[p]=item_n;}
} fac;
void prework(int n){
for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i) fac.ins(j,i);
}
struct node{int l,r,tag,mx;ll sum;} s[MAXN*4+5];
void pushup(int k){
s[k].sum=s[k<<1].sum+s[k<<1|1].sum;
s[k].mx=max(s[k<<1].mx,s[k<<1|1].mx);
}
void pushdown(int k){
if(s[k].tag!=0){
s[k<<1].mx=s[k].tag;s[k<<1].tag=s[k].tag;
s[k<<1].sum=1ll*(s[k<<1].r-s[k<<1].l+1)*s[k].tag;
s[k<<1|1].mx=s[k].tag;s[k<<1|1].tag=s[k].tag;
s[k<<1|1].sum=1ll*(s[k<<1|1].r-s[k<<1|1].l+1)*s[k].tag;
s[k].tag=0;
}
}
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(l==r){s[k].sum=l;s[k].mx=l;return;}
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}
void modify(int k,int l,int r,int x){
if(l<=s[k].l&&s[k].r<=r){
s[k].tag=x;s[k].mx=x;
s[k].sum=1ll*(s[k].r-s[k].l+1)*x;return;
} pushdown(k);int mid=s[k].l+s[k].r>>1;
if(r<=mid) modify(k<<1,l,r,x);
else if(l>mid) modify(k<<1|1,l,r,x);
else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
pushup(k);
}
int get_first_le(int k,int x){//find the first element >= x
if(s[k].l==s[k].r) return s[k].l;
pushdown(k);
if(s[k<<1|1].mx<x) return s[k].r+1;
else if(s[k<<1].mx<x) return get_first_le(k<<1|1,x);
else return get_first_le(k<<1,x);
}
void deal_max(int l,int r,int x){
if(l>r) return;
int pos=get_first_le(1,x)-1;
// printf("%d %d %d %d\n",l,r,x,pos);
if(pos>r) pos=r;if(pos<l) return;
modify(1,l,pos,x);
}
int main(){
scanf("%d",&n);prework(MAXN);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) for(int e=fac.hd[a[i]];e;e=fac.nxt[e])
pos[fac.v[e]].pb(i);
build(1,1,n);ll ans=0;
for(int i=MAXN;i;i--){
if(pos[i].size()>=2){
int fst=pos[i][0],fst_se=pos[i][1];
int lst=pos[i][pos[i].size()-1],lst_se=pos[i][pos[i].size()-2];
deal_max(1,fst,lst_se);
deal_max(fst+1,fst_se,lst);
deal_max(fst_se+1,n,n+1);
} ans+=s[1].sum-1ll*n*(n+1)/2;
// printf("%d %lld\n",i,s[1].sum);
} printf("%lld\n",ans);
return 0;
}

Codeforces 671C - Ultimate Weirdness of an Array(线段树维护+找性质)的更多相关文章

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

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

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

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

  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. Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...

  5. Codeforces 1114F Please, another Queries on Array? 线段树

    Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...

  6. Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵

    E. Sasha and Array 题目连接: http://codeforces.com/contest/719/problem/E Description Sasha has an array ...

  7. Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]

    Codeforces 洛谷:咕咕咕 CF少有的大数据结构题. 思路 考虑一些欧拉函数的性质: \[ \varphi(p)=p-1\\ \varphi(p^k)=p^{k-1}\times (p-1)= ...

  8. CF719E. Sasha and Array [线段树维护矩阵]

    CF719E. Sasha and Array 题意: 对长度为 n 的数列进行 m 次操作, 操作为: a[l..r] 每一项都加一个常数 C, 其中 0 ≤ C ≤ 10^9 求 F[a[l]]+ ...

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

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

随机推荐

  1. Golang通脉之数据类型

    标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字 标识符 在编程语言中标识符就是定义的具有某种意义的词,比如变量名.常量名.函数名等等. Go语言中标识符允许由字母数字和_(下划线) ...

  2. 兜底机制——leader到底做了什么?

    Case 在之前一次年底考评的时候,有一位leader将一个案例同时用到了自己和下属身上,老板发出了责问: 这个项目到底你是负责人,还是你下面的同学是负责人,如果下面的同学是负责人,为什么要算到你的头 ...

  3. 使用vue-cli+webpack搭建vue开发环境

    在这里我真的很开心,好久没有用过博客,今天突然看到了我的博客有不少人看过,虽然没有留下脚印,但是还是激起了我重新拿起博客的信心,感谢大家. 在这里我们需要首先下载node,因为我们要用到npm包下载, ...

  4. 【UE4 C++】 UDataAsset、UPrimaryDataAsset 的简单使用

    UDataAsset 简介 用来存储数据,每一个DataAsset 都是一份数据 可以派生,系统自带派生 UPrimaryDataAsset 方便数据对象的加载和释放 可以引用其他的 UDataAss ...

  5. 这12种场景Spring事务会失效!

    前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了.在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性 (要么同时成功,要么同时失败),避免数据 ...

  6. [no code][scrum meeting] Beta 4

    例会时间:5月16日11:30,主持者:伦泽标 下次例会时间:5月18日11:30,主持者:叶开辉 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 完成整体框架设计与登录逻辑 与后端对接 ...

  7. 期望dp好题选做

    前言: 最近连考两场期望dp的题目,sir说十分板子的题目我竟然一点也不会,而且讲过以后也觉得很不可改.于是开个坑. 1.晚测10 T2 大佬(kat) 明明有\(O(mlog)\)的写法,但是\(m ...

  8. Java RMI学习与解读(二)

    Java RMI学习与解读(二) 写在前面 接上篇文章,这篇主要是跟着看下整个RMI过程中的源码并对其做简单的分析 RMI源码分析 还是先回顾下RMI流程: 创建远程对象接口(RemoteInterf ...

  9. 使用 ASP.NET Core 3.1 的微服务开发指南

    使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...

  10. cm0 逆向分析

    目录 cm0 逆向分析 前言 Strings工具复习 String工具使用说明 Strings工具解cm0题 cm0 逆向分析 前言 Emmmmm,我假装你看到这里已经学过了我的<恶意代码分析实 ...