题意:
小D有个数列a ,当一个数对(i,j)(i≤j)(i,j)(i\leq j)(i,j)(i≤j)满足 aia_iai​和 aj​a_j​aj​​ 的积不大于 ai,ai+1​,.........,aj​a_i, a_{i+1}​,.........,a_j​ai​,ai+1​​,.........,aj​​中的最大值时,小D认为这个数对是美丽的.请你求出美丽的数对的数量。
n≤1e5n \leq1e5n≤1e5
ai≤1e9a_i \leq1e9ai​≤1e9
有人推荐笛卡尔树的练习题?但是怎么也想不到用笛卡尔树做…
跟在笛卡尔树上分治一样…只不过ST表换成了笛卡尔树
题解:
分治+主席树+ST表

每次找出区间[l,r][l,r][l,r]之间最大值的下标midmidmid(ST表查找即可)
然后枚举l到midl到midl到mid的每个数,每次区间询问mid到r之间数小于等于⌊amidai⌋\lfloor \frac{a_{mid}}{a_i} \rfloor⌊ai​amid​​⌋
但是我们会发现,极端情况下会被卡成O(n2log2n)O(n^2log^2n)O(n2log2n)
那么我们借用启发式的思想,每次去枚举区间长度小的那一半,查询大的一半即可。
为什么这样做是正确的呢?
这其实就相当于枚举了每一个点,进行查询,并且不会出现重复的情况。
比如说当前查找的区间为[l,r][l,r][l,r],查询出来的数对数量是跨过mid的数对数量,下一个查询的区间就是[l,mid−1],[mid+1,r][l,mid-1],[mid+1,r][l,mid−1],[mid+1,r]这两个小区间了,因为这两个小区间根本不会存在跨过mid的数对,那个大区间也不存在不跨过的数对,所以不存在重复的情况。

代码:

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;const int maxn=1e5+10;int a[maxn],ans;
int sum[maxn*50];
int lc[maxn*50],rc[maxn*50];
int rt[maxn],cnt,n,p;void update(int &node,int start,int ends,int lst,int pos){node=++cnt;lc[node]=lc[lst];rc[node]=rc[lst];sum[node]=sum[lst]+1;if(start==ends) return ;int mid=(start+ends)/2;if(pos<=mid) update(lc[node],start,mid,lc[lst],pos);else update(rc[node],mid+1,ends,rc[lst],pos);
}
int query(int start,int ends,int l,int r,int x,int y){if(l<=start&&ends<=r){return sum[y]-sum[x];}int mid=(start+ends)>>1;int ans=0;if(l<=mid) ans+=query(start,mid,l,r,lc[x],lc[y]);if(mid<r) ans+=query(mid+1,ends,l,r,rc[x],rc[y]);return ans;
}int stmax[maxn][21];
int mn[maxn];int stcmpmax(int x,int y){return a[x]>a[y]?x:y;
}void init(){mn[0]=-1;for (int i=1;i<=n;i++){mn[i]=((i & (i-1))==0) ? mn[i-1]+1 : mn[i-1];stmax[i][0]=i;}for (int j=1;j<=mn[n];j++)for (int i=1;i+(1<<j)-1<=n;i++){stmax[i][j]=stcmpmax(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);}
}
int rmq_max(int L,int R)
{int k=mn[R-L+1];return stcmpmax(stmax[L][k],stmax[R-(1<<k)+1][k]);
}void divide(int l,int r){if(r<l) return ;if(l==r){if(a[l]==1) ans++;//cout<<"debug  "<<a[l]<<endl;return ;}int pre=ans;int mid=rmq_max(l,r);//cout<<"debug  "<<mid<<endl;if(mid-l<r-mid){for(int i=l;i<=mid;i++){int nowx=a[mid]/a[i];ans+=query(1,p,1,nowx,rt[mid-1],rt[r]);}}else{for(int i=mid;i<=r;i++){int nowx=a[mid]/a[i];ans+=query(1,p,1,nowx,rt[l-1],rt[mid]);}}//cout<<"debug  "<<l<<" "<<r<<" "<<mid<<" "<<ans-pre<<endl;divide(l,mid-1);divide(mid+1,r);
}signed main(){ios::sync_with_stdio(false);cin.tie(0);//freopen("out.txt","w",stdout);cin>>n;for(int i=1;i<=n;i++){cin>>a[i];p=max(p,a[i]);}init();for(int i=1;i<=n;i++){update(rt[i],1,p,rt[i-1],a[i]);}divide(1,n);cout<<ans<<endl;
}

P4755 Beautiful Pair (数据结构+分治)相关推荐

  1. 洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a,现在一个数对 ( i , j ) 如果满足 a[ i ] * a[ j ] <=max( a[ i ] ~ a[ j ] ),则称其 ...

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

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

  3. 【笛卡尔树】【树状数组】Beautiful Pair(P4755)

    正题 P4755 题目大意 给你n个数,问你有多少对二元组 (i,j)(i,j)(i,j) 满足 i≤ji\leq ji≤j 且 ai×aj≤maxi=ijaia_i\times a_j\leq ma ...

  4. 微服务架构中的key-value pair数据结构

    图中4和6橙色部分意味着WebSocket Server for WebShop的RAM里维护的一个key-value pair的数据结构,key为transaction ID,值为对应的WebSho ...

  5. luoguP4755 Beautiful Pair

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

  6. Luogu 4755 Beautiful Pair

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

  7. Java 编程技巧之数据结构

    Photo @markusspiske 文 | 常意 导读 唐宋八大家之一欧阳修在<卖油翁>中写道: 翁取一葫芦置于地,以钱覆其口,徐以杓酌油沥之,自钱孔入,而钱不湿.因曰:"我 ...

  8. 阿里巴巴工程师:Java 编程技巧之数据结构

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"1024"获取公众号专属1024GB资料 来源:阿里巴巴中间件 导读 编码过程中踩过的 ...

  9. C++知识点30——使用C++标准库(关联容器map及其初始化,赋值,查找,添加,删除与迭代器失效)

    一.关联容器简介 关于顺序容器和关联容器的区别已经在博客https://blog.csdn.net/Master_Cui/article/details/107427911中提过 C++标准库中的关联 ...

最新文章

  1. 潜入java内存结构
  2. 大话设计模式(二 代码规范、重构)
  3. boost::process::shell相关的测试程序
  4. fork创建多个子进程
  5. CodeForces 580A Kefa and First Steps
  6. JAVA之编译期和运行期区别
  7. 实现python扩展的C API方法过程全纪录(windows)
  8. 实训项目四 powerpoint 综合应用_【深化改革结硕果】新疆番茄综合精深加工关键技术及产业化应用项目取得重大突破...
  9. 给窗口添加背景图的案例
  10. 全面深入介绍C++字符串:string类
  11. web前端(2)——了解什么是前端,以及与后端的关系
  12. 背景复合写法(HTML、CSS)
  13. Spring项目启动后报连接MYSQL错误两则
  14. 【python】多进程返回值比较
  15. 全能电子地图下载器 破解版 亲测可用
  16. WDS+MDT网络部署操作系统
  17. U盘无法格式化--量产工具成功救活
  18. Discuz!您当前的访问请求当中含有非法字符,已经被系统拒绝解决办法
  19. 工业相机及镜头的相关概念与相机及镜头的选型
  20. UG/NX二次开发-阿飞博客专栏目录(九块九抄代码)

热门文章

  1. Jupyter notebook 指定 Python 解释器 anaconda
  2. Linux之绝对路径和相对路径
  3. ACMNO.30 C语言-宏交换 定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。
  4. 技术02期:这么做竟然能让你的hive运行得更流畅!
  5. 在C++平台上部署PyTorch模型流程+踩坑实录
  6. 从传感器到算法原理,机器人、视觉避障尽在此文
  7. 22.加密与安全相关,证书申请CA(gpg,openssl)
  8. 好程序员web前端分享值得参考的css理论:OOCSS、SMACSS与BEM
  9. 【2019雅礼集训】【CF 960G】【第一类斯特林数】【NTT多项式】permutation
  10. HTML 5 应用程序缓存