分治 + 主席树。

设$solve(l, r)$表示当前处理到$[l, r]$区间的情况,我们可以找到$[l, r]$中最大的一个数的位置$mid$,然后扫一半区间计算一下这个区间的答案。

注意,这时候左半边是$[l, mid]$,而右区间是$[mid, r]$,我们在这个区间处理的时候要算完所有$mid$的情况,然后我们每一次分治的时候去处理$solve(l, mid - 1)$和$solve(mid + 1, r)$,要不然当$mid$是端点的时候就会无限递归下去。

问题转化快速算出一个区间内$\leq$一个数的数,只要一棵主席树就可以解决了,区间最大值可以用$ST$表维护出来。

我们每一次选取一个比较短的区间去枚举然后算另一个区间的答案,这样子每一次计算区间的长度至少减少一半,这样子可以保证时间复杂度。

时间复杂度$O(nlog^2n)$。

Code:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = 1e5 + ;
const int Lg = ;
const ll inf = 1LL << ; int n, tot = ;
ll ans = 0LL, a[N], num[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} template <typename T>
inline void chkMax(T &x, T y) {
if(y > x) x = y;
} namespace ST {
int st[N][Lg], len[N]; inline int bet(int x, int y) {
return a[x] > a[y] ? x : y;
} inline void prework() {
for(int j = ; j <= ; j++)
for(int i = ; i + ( << j) - <= n; i++)
st[i][j] = bet(st[i][j - ], st[i + ( << (j - ))][j - ]);
} inline int qMax(int x, int y) {
int k = len[y - x + ];
return bet(st[x][k], st[y - ( << k) + ][k]);
} } using namespace ST; namespace SegT {
struct Node {
int lc, rc;
ll sum;
} s[N * ]; int root[N], nodeCnt = ; #define lc(p) s[p].lc
#define rc(p) s[p].rc
#define sum(p) s[p].sum
#define mid ((l + r) >> 1) void ins(int &p, int l, int r, int x, int pre) {
s[p = ++nodeCnt] = s[pre];
++sum(p);
if(l == r) return; if(x <= mid) ins(lc(p), l, mid, x, lc(pre));
else ins(rc(p), mid + , r, x, rc(pre));
} ll query(int r1, int r2, int l, int r, int x, int y) {
if(x > y) return 0LL;
if(x <= l && y >= r) return sum(r2) - sum(r1); ll res = 0LL;
if(x <= mid) res += query(lc(r1), lc(r2), l, mid, x, y);
if(y > mid) res += query(rc(r1), rc(r2), mid + , r, x, y);
return res;
} #undef mid } using namespace SegT; void solve(int l, int r) {
if(l > r) return; int mid = qMax(l, r);
if(mid - l < r - mid) {
for(int i = l; i <= mid; i++) {
int pos = upper_bound(num + , num + + tot, (ll) (num[a[mid]] / num[a[i]])) - num - ;
ans += query(root[mid - ], root[r], , tot, , pos);
}
} else {
for(int i = mid; i <= r; i++) {
int pos = upper_bound(num + , num + + tot, (ll) (num[a[mid]] / num[a[i]])) - num - ;
ans += query(root[l - ], root[mid], , tot, , pos);
}
} solve(l, mid - ), solve(mid + , r);
} int main() {
read(n);
for(int i = ; i <= n; i++) {
read(a[i]);
len[i] = log2(i), st[i][] = i;
num[++tot] = a[i];
}
prework(); num[++tot] = inf;
sort(num + , num + + tot);
tot = unique(num + , num + tot + ) - num - ; for(int i = ; i <= n; i++) {
a[i] = lower_bound(num + , num + + tot, a[i]) - num;
ins(root[i], , tot, a[i], root[i - ]);
} /* for(int i = 1; i <= n; i++)
printf("%lld ", a[i]);
printf("\n"); */ solve(, n); printf("%lld\n", ans);
return ;
}

Luogu 4755 Beautiful Pair的更多相关文章

  1. luogu P4755 Beautiful Pair

    luogu 这题有坨区间最大值,考虑最值分治.分治时每次取出最大值,然后考虑统计跨过这个位置的区间答案,然后两边递归处理.如果之枚举左端点,因为最大值确定,右端点权值要满足\(a_r\le \frac ...

  2. 洛谷4755 Beautiful Pair (分治)

    题目描述 小D有个数列 \(a\),当一个数对 \((i,j)(i\le j)\) 满足\(a_i\)和\(a_j\)的积 不大于 \(a_i \cdots a_j\) 中的最大值时,小D认为这个数对 ...

  3. 「LGR-049」洛谷7月月赛 D.Beautiful Pair

    「LGR-049」洛谷7月月赛 D.Beautiful Pair 题目大意 : 给出长度为 \(n\) 的序列,求满足 \(i \leq j\) 且 $a_i \times a_j \leq \max ...

  4. [luogu4755]Beautiful Pair

    [luogu4755]Beautiful Pair luogu 第一次写最大值分治感觉有点丑 每次找到最大值mid,扫小的一边,主席树查大的一边小于等于\(\frac{a[mid]}{a[i]}\)的 ...

  5. 【题解】P4755 Beautiful Pair(启发式合并的思路+分治=启发式分治)

    [题解]P4755 Beautiful Pair upd: 之前一个first second烦了,现在AC了 由于之前是直接抄std写的,所以没有什么心得体会,今天自己写写发现 不知道为啥\(90\) ...

  6. Luogu4755 Beautiful Pair 最值分治、主席树

    传送门 整天做一些模板题感觉药丸 设\(val_i\)表示第\(i\)个位置的值 看到区间最大值考虑最值分治.对于当前的区间\([l,r]\),找到区间最大值\(mid\),递归\([l,mid-1] ...

  7. luoguP4755 Beautiful Pair

    https://www.luogu.org/problemnew/show/P4755 考虑分治,在 [l, r] 区间中用线段树找到最大的一个点,处理经过它的可行数对的个数,统计个数可以离线树状数组 ...

  8. 洛谷$P4755\ Beautiful\ Pair$ 最大值分治

    正解:最大值分治 解题报告: 传送门$QwQ$ 昂考虑如果已经钦定了点$x$是这个$max$了,然后现在要求有多少对$[l,r]$满足$a_x=max\left\{a_i\right\},i\in[l ...

  9. 洛谷 P4755 - Beautiful Pair(主席树+分治+启发式优化)

    题面传送门 wssb,我紫菜 看到这类与最大值统计有关的问题可以很自然地想到分治,考虑对 \([l,r]\) 进行分治,求出对于所有 \(l\le x\le y\le r\) 的点对 \((x,y)\ ...

随机推荐

  1. EMQ (Erlang/Enterprise/Elastic MQTT Broker)

    EMQ (Erlang/Enterprise/Elastic MQTT Broker) https://www.cnblogs.com/SteveLee/p/9843215.html MQ介绍 EMQ ...

  2. JavaScript define

    1. AMD的由来 前端技术虽然在不断发展之中,却一直没有质的飞跃.除了已有的各大著名框架,比如Dojo,jQuery,ExtJs等等,很多公司也都有着自己的前端开发框架.这些框架的使用效率以及开发质 ...

  3. Windows 特殊文件夹

    收藏的XP的一些特殊文件夹,使用方法:在任意位置用以下文件名创建文件夹即可. 目前还有些可以在WIN7下正常使用,以此作为一个存档,便于日后查询.   回收站.{645ff040-5081-101b- ...

  4. ArcGIS破解配置及oracle文件配置

    1.破解配置 2.oracle文件配置

  5. 在laravel中使用支付宝手机网站支付 和 支付宝退款

    1.在蚂蚁金服开放平台中申请对应的应用,并根据提示进行签约 2.给对应的应用信息 生成私钥和公钥(私钥会保存在本地,公钥会放在对应的应用信息中) 3.下载手机网站支付 对应的php sdk 4.将sd ...

  6. ubuntu为什么没有/etc/inittab文件? 深究ubuntu的启动流程分析

    Linux 内核启动 init ,init进程ID是1,是所有进程的父进程,所有进程由它控制. Ubuntu 的启动由upstart控制,自9.10后不再使用/etc/event.d目录的配置文件,改 ...

  7. win10下默认使用福昕打开PDF

    win10为了推他的edge浏览器, 将默认的pdf打开设置为了edge浏览器, 非常令人反感, 做浏览器就好好做浏览器, 为什么要默认打开pdf? 而且修改默认为福昕后, 下次打开pdf文件, 他又 ...

  8. mysql数据增删查授权

    一 介绍 MySQL数据操作: DML ======================================================== 在MySQL管理软件中,可以通过SQL语句中的 ...

  9. C# IP地址去掉端口号

    string Ip1 = "192.168.0.199:7777"; string Ip2 = Ip1.Remove(Ip1.IndexOf(':'));

  10. Centos7 第三方仓库 yum 方式安装 PHP7.2

    1.卸载原先安装的PHP yum remove php rpm -qa|grep php #列出所有的php相关的rpm包 rpm -e xxx #xxx指的是上一个命令列出的rpm包的包名,复制即可 ...