题目链接:点击查看

题目大意:给出一个长度为 n 的数列 a,现在一个数对 ( i , j ) 如果满足 a[ i ] * a[ j ] <=max( a[ i ] ~ a[ j ] ),则称其为美丽的,求出美丽对的数量

题目分析:直接统计是比较困难的,但正难则反,我们可以枚举每个数作为最大值时,在其管辖的区间内进行统计,对于某个最大值 i 来说,肯定存在着 l[ i ] 和 r[ i ] ,使得 l[ i ] - 1 是 i 左侧首个大于 a[ i ] 的位置,r[ i ] + 1 是 i 右侧首个大于 a[ i ] 的位置,这样在区间 [ l[ i ] , r[ i ] ] 中,跨过位置 i 时的最大值一定是 a[ i ] ,于是区间就被分成了两段:[ l[ i ] , i ] , [ i , r[ i ] ],因为乘积运算满足交换律,所以遍历长度较小的一段,在另一段中查找符合条件的元素的个数即可,假设当前枚举的数字为 a[ j ] ,最大值为 a[ i ] ,所以需要在区间内查找 [ 1 , a[ i ] / a[ j ] ] 的元素个数,这显然是线段树的功能,不过如果放在区间上询问的话,就需要可持久化一下来使用,也就是主席树了,对于上述找 l[ i ] 和 r[ i ] 的过程,可以用笛卡尔树来完成,然后 dfs 一遍统计答案就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;int a[N];LL ans;
/*主席树*/
struct Node1
{int l,r;int sum;
}tree[N*35];int cnt,root[N];void update(int num,int &k,int l,int r)
{tree[cnt++]=tree[k];k=cnt-1;tree[k].sum++;if(l==r)return;int mid=l+r>>1;if(num<=mid)update(num,tree[k].l,l,mid);elseupdate(num,tree[k].r,mid+1,r);
}int query(int i,int j,int L,int R,int l,int r)//i:左端点根节点编号,j:右端点根节点编号,l,r:目标区间,L,R:当前区间
{if(l>r)return 0;if(R<l||L>r)return 0;if(L>=l&&R<=r)return tree[j].sum-tree[i].sum;int mid=L+R>>1;return query(tree[i].l,tree[j].l,L,mid,l,r)+query(tree[i].r,tree[j].r,mid+1,R,l,r);
}
/*主席树*/
/*笛卡尔树*/
struct Node2
{int l,r,val;
}t[N];stack<int>s;void insert(int x)
{while(s.size()&&t[s.top()].val<t[x].val)s.pop();t[x].l=t[s.top()].r;//x->lsont[s.top()].r=x;//fa->x(rson)s.push(x);
}
/*笛卡尔树*/
void dfs(int k,int l,int r)
{if(k==0)//特判一下根 {if(t[k].l)dfs(t[k].l,l,r);if(t[k].r)dfs(t[k].r,l,r);return;}if(k-l<=r-k)//遍历左区间 for(int i=l;i<=k;i++)ans+=query(root[k-1],root[r],1,inf,1,t[k].val/t[i].val);else//遍历右区间 for(int i=k;i<=r;i++)ans+=query(root[l-1],root[k],1,inf,1,t[k].val/t[i].val);if(t[k].l)dfs(t[k].l,l,k-1);if(t[k].r)dfs(t[k].r,k+1,r);
}void init()
{t[0].val=inf;t[0].l=t[0].r=0;s.push(0);root[0]=0;tree[0].l=tree[0].r=tree[0].sum=0;cnt=1;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&t[i].val);insert(i);root[i]=root[i-1];update(t[i].val,root[i],1,inf);}dfs(0,1,n);printf("%lld\n",ans);return 0;
}

洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)相关推荐

  1. 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

    题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...

  2. 【洛谷P3701】 「伪模板」主席树【网络流】

    题目大意: 题目链接:https://www.luogu.org/problemnew/show/P3701 byx和手气君都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家 ...

  3. 信息学奥赛一本通 1107:校门外的树 | 1931:【05NOIP普及组】校门外的树 | OpenJudge NOI 1.6 06 | 洛谷 P1047 [NOIP2005 普及组] 校门外的树

    [题目链接] ybt 1107:校门外的树 ybt 1931:[05NOIP普及组]校门外的树 OpenJudge NOI 1.6 06:校门外的树 洛谷 P1047 [NOIP2005 普及组] 校 ...

  4. 洛谷 P1873 [COCI 2011/2012 #5] EKO / 砍树

    题目传送门: 洛谷 P1873 [COCI 2011/2012 #5] EKO / 砍树 题目描述 伐木工人 Mirko 需要砍 M 米长的木材.对 Mirko 来说这是很简单的工作,因为他有一个漂亮 ...

  5. 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树(二分法)

    题目链接 : 洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树 文章目录 前言 一.题目 题目描述 输入格式 输出格式 输入输出样例 说明/提示 二.代码 前言 第一次写博客, ...

  6. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  7. P4755 Beautiful Pair (数据结构+分治)

    题意: 小D有个数列a ,当一个数对(i,j)(i≤j)(i,j)(i\leq j)(i,j)(i≤j)满足 aia_iai​和 aj​a_j​aj​​ 的积不大于 ai,ai+1​,........ ...

  8. 洛谷 2921 记忆化搜索 tarjan 基环外向树

    洛谷 2921 记忆化搜索 tarjan 传送门 (https://www.luogu.org/problem/show?pid=2921) 做这题的经历有点玄学,,起因是某个random题的同学突然 ...

  9. YBTOJ洛谷P4331:数字序列(左偏树)

    文章目录 题目描述 数据范围 解析 代码 题目描述 数据范围 n<=1e6n<=1e6n<=1e6 解析 先考虑简单情况 如果原数列是单调递增的,显然应该使bi=aib_i=a_ib ...

最新文章

  1. Tensorflow mnist 数据集测试代码 + 自己下载数据
  2. Go 语言编程 — 数据类型转换
  3. 论文翻译-机器翻译:Attention
  4. oracle 临时表存在哪里_openGauss魔改PG?它能兼容Oracle的数据库表吗?
  5. 阅读“CodeIgniter中国》文档首页》常规主题》安全”之抄录
  6. NumPy数值计算库-1
  7. qt程序使用多行linux命令,开发Qt应用程序的基本方法总结
  8. 数据结构上机实践第二周项目2- 程序的多文件组织
  9. 程序员面试金典——18.9实时中位数
  10. java重载和重写的区别_Java重载和重写的区别
  11. 北京航空航天大学计算机学院保研率,北京航空航天大学计算机学院(专业学位)计算机技术保研条件...
  12. Hadoop HFDS 的 Shell 操作
  13. 微信小程序如何分享到朋友圈
  14. c语言outl函数,如何调用outlook
  15. 数据结构复习(五)——树和二叉树
  16. 登山冒险开拓新户外精神
  17. socket用法linux,linux下socket用法
  18. css动画——语音播报小喇叭动效
  19. [安卓开发笔记一]Android开发配置opencv环境超详细教程
  20. 工作票不宜使用计算机管理,什么情况下使用动火工作票

热门文章

  1. activex控件有什么用_你知道怎样用Excel打印「条形码」吗?
  2. mysql残余文件的清理
  3. MySQL分组查询—简单使用
  4. kubernetes-Pod定义
  5. Redis中的淘汰策略
  6. MybatisPlus入门案例
  7. Spring框架的前世今生以及对Spring的宏观认识
  8. 包-封装模块、设置__init__和外界导入包
  9. 创建集群版的Eureka注册中心
  10. MySQL 1093 You can't specify target table for update in FROM c 的解决办法