[「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. bzoj3043 IncDec Sequence

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3043 [题解] 比较神奇的一道题,开始没往差分的角度上想,所以没想出来. 考虑查分数组,有$ ...

  2. GXC 钱包部署

    参考: [ 官方 wiki ] 基于 Ubuntu 的 GXC 部署 基础环境 OS: Ubuntu gxc: 官方 [ release 最新版本 ] 下载 release 包(ubuntu) cd ...

  3. gridveiw的使用

    using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI ...

  4. 【洛谷 P1525】 关押罪犯 (二分图+二分答案)

    题目链接 并查集+贪心当然是可以做的. 但我用二分图+二分答案. 二分一个\(mid\),删去所有边权小于等于\(mid\)的边,看有没有奇环存在,如果存在,则\(mid\)不行. #include ...

  5. 4 Values whose Sum is 0 POJ 2785 (折半枚举)

    题目链接 Description The SUM problem can be formulated as follows: given four lists A, B, C, D of intege ...

  6. mongodb 学习笔记--- 基础知识

    1.mongodb的安装 (1) mac使用brew 安装就好 brew install mongodb (2) mkdir /data/db 作为mongodb默认的数据目录 并 sudo chow ...

  7. hadoop中setOutputKeyClass和setOutputValueClass里类型

    初学mapreduce programing,纠结一天的问题如下: job.setOutputKeyClass和job.setOutputValueClas在默认情况下是同时设置map阶段和reduc ...

  8. VPS性能测试(2):内存大小、交换空间、高速缓存、实际使用内存

    1.要想查看购买的VPS主机的内存信息,执行:cat /proc/meminfo,主要是看内存大小.交换空间.高速缓存 2.VPS主机实际使用内存大小.Linux管理内存的机制是这样的:无论物理内存有 ...

  9. apache的扩展模块安装

    /* 当需要用到Apache的扩展模块时, 就要用到了apache的扩展工具 apxs */ #在使用这个功能之前,请先确认是否已经加载了 mod_so 模块,方法是: [root@localhost ...

  10. POJ 1456 Supermarket(贪心+并查集)

    题目链接:http://poj.org/problem?id=1456 题目大意:有n件商品,每件商品都有它的价值和截止售卖日期(超过这个日期就不能再卖了).卖一件商品消耗一个单位时间,售卖顺序是可以 ...