【题解】P4755 Beautiful Pair

upd: 之前一个first second烦了,现在AC了

由于之前是直接抄std写的,所以没有什么心得体会,今天自己写写发现

不知道为啥\(90\)分

我直接把之前写的总结kuai过来

而选取其他位置(比如序列的最大值)由不能保证复杂度。但是如果每层分治的复杂度只与较小的一侧的大小有关,那么这个复杂度就等同于启发式合并的复杂度。

一句话证明启发式合并的复杂度:一次合并至少有一个集合倍增了。

Luogu4755 Beautiful Pair(\(max\)分治)

\(max\)分治意思就是分治的时候不好取中间数作为分治中心,要选择别的特殊数进行分治,此时可以利用启发式合并的思想做到外层一个\(\log\)

给一个序列 \(\{a_i \}\),求有多少对 \(1 ≤ i ≤ j ≤ n\) 满足 \(a_i a_ j ≤ max _{k=i}^j a_ k\)。

考虑这样的做法,如何分治求这种数对,考虑这样的做法:

分治处理区间:长度为\(n,[l,r]\)并且跨过\([l,r]\)某个最大值(有多个最大值的时候随意指定一个)的所有答案区间个数:

首先随便一个数据结构维护出一段区间的最大值的位置(多个的时候随便指定一个),就把这个\([l,r]\)分成了两个区间递归下去即可。 现在复杂度的关键在于处理当前层的复杂度了,受到启发式合并的启发(大雾),我们考虑大段维护,小的朴素,考虑这样的做法:

首先对于短的那一边区间的长度必定\(\le n/2\),现在先枚举这半边区间的\(a_u\),设当前层的全局最大值为\(k\),那么我们现在要查询另一边区间中,小于等于\(\lfloor \dfrac {k}{a_u}\rfloor\)的\(a_i\)个数,这个东西直接值域主席树维护一波。主席树是一个log的。这样统计当前层的答案的复杂度是\(f(n)=O(\dfrac n 2 \log L)\)。由于每层的复杂度和当前层短的那一边有关,利用启发式合并的复杂度证明方法很容易发现这样的复杂度是\(O(n \log^2n)\)的,只要倒着看我们这个分治的递归就行了。

//@winlere
#include<iostream>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define lef l,mid,seg[pos].ls
#define rgt mid+1,r,seg[pos].rs
#define pp(x) seg[x].val=seg[seg[x].ls].val+seg[seg[x].rs].val
using namespace std; typedef long long ll; typedef const int& cint;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e5+5;
pair<int,int> st[maxn][19];
int lg[maxn],n,data[maxn],sav[maxn],len; ll ans;
inline pair<int,int> que(int l,int r){return max(st[l][lg[r-l]],st[r-(1<<lg[r-l])+1][lg[r-l]]);}
struct Chairseg{
struct E{
int ls,rs,val;
E(){ls=rs=val=0;} E(cint a,cint b,cint c){ls=a; rs=b; val=c;}
}seg[maxn*60];
int rt[maxn],cnt,n;
void build(int k,int val,int l,int r,int pos,int last){
if(l==r){seg[pos].val=seg[last].val+val;return;}
seg[pos]=seg[last];
if(k<=mid) seg[pos].ls=++cnt,build(k,val,lef,seg[last].ls);
if(k> mid) seg[pos].rs=++cnt,build(k,val,rgt,seg[last].rs);
pp(pos);
}
int que(int L,int R,int l,int r,int pos){
if(L>r||R<l||r<0) return 0;
if(L<=l&&r<=R) return seg[pos].val;
return que(L,R,lef)+que(L,R,rgt);
}
ll que(int L,int R,int l,int r){return que(l,r,1,n,rt[R])-que(l,r,1,n,rt[L-1]);}
inline void init(const int&n){this->n=n;}
}T;
inline int divd(const int&x){return upper_bound(sav+1,sav+len+1,x)-sav-1;}
void divd(int l,int r){
if(l>=r) return ans+=ll(l==r)*(data[l]==1),void();
const pair<int,int>&now=que(l,r);
if(now.second<mid)
for(int t=l;t<=now.second;++t)
ans=ans+T.que(now.second,r,1,divd(now.first/data[t]));
else
for(int t=now.second;t<=r;++t)
ans=ans+T.que(l,now.second,1,divd(now.first/data[t]));
divd(l,now.second-1); divd(now.second+1,r);
}
int main(){
n=qr();
for(int t=1;t<=n;++t) lg[t]=lg[t-1]+(1<<lg[t-1]<<1==t);
for(int t=1;t<=n;++t) st[t][0]=make_pair(data[t]=qr(),t),sav[t]=data[t];
for(int t=1;t<=lg[n];++t)
for(int i=1;i<=n;++i)
st[i][t]=max(st[i][t-1],st[min(i+(1<<t>>1),n)][t-1]);
sav[n+1]=1e9+1;
sort(sav+1,sav+n+2);
len=unique(sav+1,sav+n+2)-sav-1;
T.init(len);
for(int t=1;t<=n;++t) T.build(divd(data[t]),1,1,T.n,T.rt[t]=++T.cnt,T.rt[t-1]);
divd(1,n);
printf("%lld\n",ans);
return 0;
}

【题解】P4755 Beautiful Pair(启发式合并的思路+分治=启发式分治)的更多相关文章

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

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

  2. luogu P4755 Beautiful Pair

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

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

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

  4. P4755 Beautiful Pair

    题目 洛谷 做法 \(i≤x≤j,a[i]<\frac{a[x]}{a[j]}\) 考虑\(a[x]\)的贡献,单调栈预处理\(L,R\)能作为最大值的区间 枚举一端点,仅需另一端点满足条件即可 ...

  5. P4755 Beautiful Pair (分治 + 主席树)

    题意:1e5的数组 计算有多少对 ai * aj <= max(ai ai+1...aj-1 aj) 题解:在处理这种涉及到区间极值的题时 好像是个套路分治 从级值中间分成两个区间 从区间短的那 ...

  6. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

  7. 【BZOJ2733】[HNOI2012] 永无乡(启发式合并Splay)

    点此看题面 大致题意: 给你一张图,其中每个点有一个权值,有两种操作:在两点之间连一条边,询问一个点所在联通块第\(k\)小的权值. 平衡树 看到第\(k\)小,应该不难想到平衡树. 为了练习\(Sp ...

  8. 【主席树启发式合并】【P3302】[SDOI2013]森林

    Description 给定一个 \(n\) 个节点的森林,有 \(Q\) 次操作,每次要么将森林中某两点联通,保证操作后还是个森林,要么查询两点间权值第 \(k\) 小,保证两点联通.强制在线. L ...

  9. HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Tota ...

随机推荐

  1. @atcoder - AGC035F@ Two Histograms

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N*M 的方格,我们通过以下步骤往里面填数: (1)将 ...

  2. LeetCode Weekly Contest 6

    leetcode现在每周末举办比赛,这是今天上午参加的比赛的题解.题目难度不算大,两个easy,一个medium,一个hard.hard题之前接触过,所以做得比较顺利. 1.  Sum of Left ...

  3. 【学生研究课题】CSDN博客数据获取、分析、分享

    题记     这次<对象程序设计>课程设计,一共给定了8个选题(下载WORD版.PDF版),以及自由选题的机会.从大家初步选题结果来看(图1).绝大部分同学选择了"图形用户界面的 ...

  4. 全文索引——CONTAINS 语法

    Like直接在数据据中查找可以查到所有所需记录但是会扫描整个表会影响性能CONTAINS是基于全文索引进行查询,查询结果受系统全文索引分词的方法影响查询结果会不全.Select * FROM A Wh ...

  5. 小程序加载大图片 使用widthFix时,图片先拉伸然后才显示完全

    <image src="http://www.ll.com/sss.jpg" mode="widthFix" style="width:180r ...

  6. springboot2.04与activiti 6.0集成

    本文就不对activiti做解释,下面直接看项目集成 以下顺序方面根据我的理解来,可以先从第二章看,再看第一张与第三章 增加activiti表的API,备注用. 目录 一.springboot2.X集 ...

  7. 如何用简单易懂的例子解释条件随机场(CRF)模型?它和HMM有什么区别?

    https://www.zhihu.com/question/35866596/answer/418341940

  8. 2019-10-19-dotnet-给MatterMost订阅RSS博客

    title author date CreateTime categories dotnet 给MatterMost订阅RSS博客 lindexi 2019-10-19 08:12:36 +0800 ...

  9. turtle 20秒画完小猪佩奇“社会人”

    转载:https://blog.csdn.net/csdnsevenn/article/details/80650456 图片源自网络 作者 丁彦军 如需转载,请联系原作者授权. 今年社交平台上最火的 ...

  10. Lavarel之环境配置 .env

    .env 文件位于项目根目录下,作为全局环境配置文件. 1. 配置参数 // 运行环境名称 APP_ENV=local // 调试模式,开发阶段启用,上线状态禁用. APP_DEBUG=true // ...