P4755-Beautiful Pair【笛卡尔树,线段树】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P4755


1|1题目大意

n个数字的一个序列,求有多少个点对i,j满足ai×ajmax{ak}(k[l,r])


1|2解题思路

如果构建一棵笛卡尔树的话那么两个点之间的max就在笛卡尔树的LCA位置。

所以对于每个位置维护一个线段树,然后每次暴力枚举小的那棵子树在大子树的线段树中查询即可。然后线段树合并或者启发式合并上去就好了。

建笛卡尔树的时候用RMQ查询区间最大值然后递归下去就好了。

当然因为是乘法所以小的那个值域不会超过109所以也可以树状数组+启发式合并。

这里写的是线段树的做法,时间复杂度都是O(nlog2n)

注意1要特判就好了


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10,L=20; int n,a[N],lg[N],f[N][L+1],inf; long long ans; struct Seg_Tree{ int cnt,w[N<<6],ls[N<<6],rs[N<<6]; void Change(int &x,int L,int R,int pos,int val){ if(!x)x=++cnt;w[x]+=val; if(L==R)return; int mid=(L+R)>>1; if(pos<=mid)Change(ls[x],L,mid,pos,val); else Change(rs[x],mid+1,R,pos,val); return; } int Ask(int x,int L,int R,int l,int r){ if(!x||l>r)return 0; if(L==l&&R==r)return w[x]; int mid=(L+R)>>1; if(r<=mid)return Ask(ls[x],L,mid,l,r); if(l>mid)return Ask(rs[x],mid+1,R,l,r); return Ask(ls[x],L,mid,l,mid)+Ask(rs[x],mid+1,R,mid+1,r); } int Merge(int x,int y,int L,int R){ if(!x||!y)return x+y; int mid=(L+R)>>1;w[x]+=w[y]; if(L==R)return x; ls[x]=Merge(ls[x],ls[y],L,mid); rs[x]=Merge(rs[x],rs[y],mid+1,R); return x; } }T; int Ask(int l,int r){ int z=lg[r-l+1]; int x=f[l][z],y=f[r-(1<<z)+1][z]; return (a[x]>=a[y])?x:y; } int solve(int l,int r){ if(l>r)return 0; int x=Ask(l,r),ls,rs; ls=solve(l,x-1); rs=solve(x+1,r); if(ls)ans+=T.Ask(ls,1,inf,1,1); if(rs)ans+=T.Ask(rs,1,inf,1,1); if(x-l<=r-x){ for(int i=l;i<x;i++) ans+=T.Ask(rs,1,inf,1,a[x]/a[i]); } else{ for(int i=x+1;i<=r;i++) ans+=T.Ask(ls,1,inf,1,a[x]/a[i]); } ls=T.Merge(ls,rs,1,inf); T.Change(ls,1,inf,a[x],1); return ls; } int main() { // printf("%d\n",sizeof(T)>>20); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); inf=max(inf,a[i]); ans+=(a[i]==1); f[i][0]=i; } inf=1e9; for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++){ int x=f[i][j-1],y=f[i+(1<<j-1)][j-1]; if(a[x]>=a[y])f[i][j]=x; else f[i][j]=y; } solve(1,n); printf("%lld",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14296386.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(53)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示