[「LGR-049」洛谷7月月赛 D.Beautiful Pair](https://www.luogu.org/problemnew/show/P4755)

题目大意 : 给出长度为 \(n\) 的序列,求满足 \(i \leq j\) 且 $a_i \times a_j \leq \max(a_i..a_j) $ 的点对\((i, j)\)的数量

\(n \leq 10^5 \ 1 \leq a_i \leq 10^9\)

解题思路 :

直接枚举某一端点貌似很难维护极值,不妨对于每一个极值 \(a_k\),求 $ \max(a_i..a_j) \leq a_k$ 且 \(i \leq k \leq j\) 的点对数

考虑一个每一个点能作为\(\max\)统治的区间可以用单调栈求,并构建出笛卡尔树

此时对于每一个 \(a_k\) 答案由两部分产生:

  1. 点对 \((i, j)\) 满足 \(i = k\) 或 $j = k $,这一部分答案比较简单,就是统治区间内 \(1\) 的个数
  2. 点对 \((i, j)\) 满足 \(i \neq k\) 且 \(j \neq k\) ,此时答案等价于点 \(k\) 在笛卡尔树上的节点的左右子树中各取一个组成合法点对的方案数

第一种情况可以直接前缀和计算,在此不多做讨论,主要看第二种情况

由于是树上的子树问题,我们很容易想到用 \(dsu \ on\ tree\) 的做法来解决

不了解 \(dsu \ on \ tree\) 的可以戳这里的链接

枚举子树大小较小的子树,用树状数组维护较大的子树产生的贡献

对于较小子树中的点 \(u\) ,能与其组成合法点对的点 \(x\) 要满足 \(\frac{maxval}{a_u} \leq a_x\),直接用树状数组统计前缀和即可

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define N (500005)
#define int ll
int a[N], b[N], n, ans;
namespace Ls{
int s[N]; int lens = 0;
inline int calc(int x){
int res = upper_bound(s + 1, s + lens + 1, x) - s - 1;
return res;
}
inline void Realmain(){
for(int i = 1; i <= n; i++) s[i] = a[i];
sort(s + 1, s + n + 1);
lens = unique(s + 1, s + n + 1) - s - 1;
}
}
struct Fenwick{
int s[N];
inline int lowbit(int x){ return x & -x; }
inline void add(int x, int v){
for(int i = x; i <= n; i += lowbit(i)) s[i] += v;
}
inline int query(int x){
int ans = 0;
for(int i = x; i; i -= lowbit(i)) ans += s[i];
return ans;
}
}Bit;
namespace Treap{
int sz[N], ch[N][2], s[N], l[N], r[N], st[N], top;
inline void Getsize(int u){
sz[u] = 1;
int ls = ch[u][0], rs = ch[u][1];
if(ls) Getsize(ls), sz[u] += sz[ls];
if(rs) Getsize(rs), sz[u] += sz[rs];
if(!u) sz[u] = 0;
}
inline void Add(int u){
Bit.add(b[u], 1);
if(ch[u][0]) Add(ch[u][0]);
if(ch[u][1]) Add(ch[u][1]);
}
inline void Clear(int u){
Bit.add(b[u], -1);
if(ch[u][0]) Clear(ch[u][0]);
if(ch[u][1]) Clear(ch[u][1]);
}
inline int Count(int u, int val){
int pos = Ls::calc(val / a[u]);
int res = Bit.query(pos);
if(ch[u][0]) res += Count(ch[u][0], val);
if(ch[u][1]) res += Count(ch[u][1], val);
return res;
}
inline void solve(int u){
int p = sz[ch[u][0]] > sz[ch[u][1]] ? 0 : 1;
int ms = ch[u][p], ls = ch[u][p^1];
if(ls) solve(ls), Clear(ls);
if(ms) solve(ms);
if(ls) ans += Count(ls, a[u]);
if(u){ if(ls) Add(ls); Bit.add(b[u], 1); }
}
inline void Build(){
for(int i = 1; i <= n; i++){
while(a[st[top]] <= a[i] && top) r[st[top--]] = i - 1;
int f = st[top]; l[i] = f + 1;
ch[i][0] = ch[f][1], ch[f][1] = i, st[++top] = i;
}
for(int i = 1; i <= n; i++) if(!r[i]) r[i] = n;
}
inline void Realmain(){
Build(), Getsize(0), solve(0);
for(int i = 1; i <= n; i++) s[i] = s[i-1] + (a[i] == 1 ? 1 : 0);
for(int i = 1; i <= n; i++) ans += s[r[i]] - s[l[i]-1];
cout << ans << endl;
}
}
main(){
read(n);
for(int i = 1; i <= n; i++) read(a[i]);
Ls::Realmain();
for(int i = 1; i <= n; i++) b[i] = Ls::calc(a[i]);
Treap::Realmain();
return 0;
}

「LGR-049」洛谷7月月赛 D.Beautiful Pair的更多相关文章

  1. 「P4994」「洛谷11月月赛」 终于结束的起点(枚举

    题目背景 终于结束的起点终于写下句点终于我们告别终于我们又回到原点…… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演.如果这次 NO ...

  2. 「P4996」「洛谷11月月赛」 咕咕咕(数论

    题目描述 小 F 是一个能鸽善鹉的同学,他经常把事情拖到最后一天才去做,导致他的某些日子总是非常匆忙. 比如,时间回溯到了 2018 年 11 月 3 日.小 F 望着自己的任务清单: 看 iG 夺冠 ...

  3. 「LuoguP4995」「洛谷11月月赛」 跳跳!(贪心

    题目描述 你是一只小跳蛙,你特别擅长在各种地方跳来跳去. 这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 ii 块的石头高度为 h_ihi​,地面的高度是 h_0 = 0 ...

  4. 「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数

    「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数 题面描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数, ...

  5. 洛谷4月月赛R2

    洛谷4月月赛R2 打酱油... A.koishi的数学题  线性筛约数和就可以\(O(N)\)了... #include <iostream> #include <cstdio> ...

  6. 洛谷3月月赛 R1 Step! ZERO to ONE

    洛谷3月月赛 R1 Step! ZERO to ONE 普及组难度 290.25/310滚粗 t1 10分的日语翻译题....太难了不会... t2 真·普及组.略 注意长为1的情况 #include ...

  7. 【洛谷5月月赛】玩游戏(NTT,生成函数)

    [洛谷5月月赛]玩游戏(NTT,生成函数) 题面 Luogu 题解 看一下要求的是什么东西 \((a_x+b_y)^i\)的期望.期望显然是所有答案和的平均数. 所以求出所有的答案就在乘一个逆元就好了 ...

  8. 【LGR-054】洛谷10月月赛II

    [LGR-054]洛谷10月月赛II luogu 成功咕掉Codeforces Round #517的后果就是,我\(\mbox{T4}\)依旧没有写出来.\(\mbox{GG}\) . 浏览器 \( ...

  9. 【LGR-051】洛谷9月月赛

    [LGR-051]洛谷9月月赛 luogu 签到题 description 给出\(K\)和质数\(m\),求最小的\(N\)使得\(111....1\)(\(N\)个\(1\))\(\equiv k ...

随机推荐

  1. TOYS(计算几何基础+点与直线的位置关系)

    题目链接:http://poj.org/problem?id=2318 题面: TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submiss ...

  2. 中南oj String and Arrays

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?cid=2072&pid=1 Problem B: String and Arrays T ...

  3. redis基础之开机自启动和监听(二)

    redis安装好后,每次手动启动很不方便,配置开机自启动. 方法一:设置启动命令到/etc/rc.d/rc.local rc.local文件是系统全局脚本文件,会在其他开机进程脚本文件执行完毕后执行该 ...

  4. Linux 内核同步之自旋锁与信号量的异同【转】

    转自:http://blog.csdn.net/liuxd3000/article/details/8567070 Linux 设备驱动中必须解决的一个问题是多个进程对共享资源的并发访问,并发访问会导 ...

  5. linux-open-source-development-tools【重点】

    https://www.pluralsight.com/blog/software-development/linux-open-source-development-tools https://ww ...

  6. plus.networkinfo.getCurrentType()

    HTML5+API device Device Device模块管理设备信息,用于获取手机设备的相关信息,如IMEI.IMSI.型号.厂商等.通过plus.device获取设备信息管理对象. 对象: ...

  7. 关于ASP .NET Core在跨平台的linux ubuntun,SUSE ,Mac OS的发布的相关平台操作

    https://www.microsoft.com/net/learn/get-started/linuxopensuse

  8. JVM内存分配与回收

    1.内存分配与回收策略 内存自动管理:自动化的解决了对象内存分配和回收对象内存的问题. 一般在堆上分配对象,也可能经过JTI编译后间接在栈上分配. 主要分配在新生代的Eden区,如果启动了本地线程分配 ...

  9. 常用模块二(hashlib、configparser、logging)

    阅读目录 常用模块二 hashlib模块 configparse模块 logging模块   常用模块二 返回顶部 hashlib模块 Python的hashlib提供了常见的摘要算法,如MD5,SH ...

  10. 关于Sphinx中使用 RealTime Index的问题

    我们有了完整索引和增量索引,为什么还需要研究实时索引? 1.完整索引每个晚上空闲时执行一次,时间较长,但问题不大,因为IO慢,CPU累,但那个时间段基本没有人使用平台,比如凌晨2点. 2.增量索引:目 ...