思路:
正反两个 CDQ ,
ll[i] // 从左到右最长序列
rr[i] // 从右到左最长序列
lnum[i] //包含 i 这个数,有多少个最优方案,从左到右
rnum[i] //包含 i 这个数,有多少个最优方案, 从右到左。
这个题首先要离散化,
CDQ 我们先
递归先找左面的,
然后当前点的,
最后递归找右面的。(这个是第一遍 CDQ ,第二遍CDQ 我们要从右向左找。)
然后正着一遍 CDQ ,求出来从左到右的最长序列,以及选了这个点的方案数。
然后倒着一遍 CDQ ,求出来从右到左的最长序列,以及选了这个点的方案数。
最终答案就是 (lnum[i] * rnum[i] / ans), ans 是总的最优方案数。
我们用CDQ 的时候,需要用 线段树维护两个值,
一个是最长序列,一个是满足最长序列有多少个方案。
方案数随着 最长序列的改变而改变。
#include<bits/stdc++.h>
#define ls (now << 1)
#define rs (now << 1 | 1)
using namespace std;