6305.RMQ Similar Sequence

这个题的意思就是对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0,1]的实数,B的重量为B的所有元素的和,否则为0。问你B的期望重量是多少。

dls讲题说是笛卡尔树,笛卡尔树是一种特定的二叉树数据结构,具体的看这篇博客吧:【pushing my way】笛卡尔树

这个题就是笛卡尔树同构的问题,假设A的笛卡尔树的子树大小为sz[u],那么序列B与A同构的概率为,因为B中的数满足均匀分布(因为B中的元素为[0,1]中的任意实数),所以每个位置的期望值为(0+1)/2,那么B的重量总和为n/2,所以B的重量的期望值为

贴一下官方题解:

RMQ-Similar实际上就是A和B的笛卡尔树一样,这样我们就有了一个二叉树,然后可以在树上分析了。 考虑到B中有元素相同的概率是0,于是可以假设B里面元素互不相同,也就是说可以假定是一个排列。 显然,符合笛卡尔树的排列就是这个树的拓扑序列个数,就是。然后显然每个排列期望的和是,于是答案就是

代码(参考别人的模板):

 //1008-6305-RMQ的概念、笛卡尔树模板题,同构求bi的拓扑序个数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cassert>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=1e6+;
const int inf=0x3f3f3f3f;
const int mod=1e9+; stack<int>st;
ll inv[maxn];
int n; struct node{
int val,sz;
int l,r,par;
}t[maxn]; void init()
{
for(int i=;i<=n;i++)
t[i].l=,t[i].r=,t[i].par=,t[i].sz=;//初始化
t[].val=inf;
while(!st.empty())
st.pop();
st.push();
} void build()
{
for(int i=;i<=n;i++){
while(!st.empty()&&t[st.top()].val<t[i].val)//从栈顶往栈底遍历,
st.pop();
int par=st.top();
t[i].par=par;//i.par为st.pop()
t[i].l=t[par].r;
t[t[par].r].par=i;
t[par].r=i;//右子树
st.push(i);
}
} void dfs(int u)
{
if(u==) return ;
t[u].sz=;
dfs(t[u].l);
dfs(t[u].r);
t[u].sz+=t[t[u].l].sz+t[t[u].r].sz;
} void Inv(){//扩展gcd求逆元
inv[]=;
for(int i=;i<maxn;i++)
inv[i]=inv[mod%i]*(mod-mod/i)%mod;
} int main()
{
int T;
Inv();
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=;i<=n;i++)
scanf("%d",&t[i].val);
build();
dfs(t[].r); ll ans=n*inv[]%mod;
for(int i=;i<=n;i++)
ans=ans*inv[t[i].sz]%mod;
printf("%lld\n",ans);
}
}

代码(标程):

 #include <cstdio>
#include <functional>
#include <algorithm>
#include <vector>
#include <queue> using int64 = long long; const int mod = 1e9 + ; int main() {
int T;
scanf("%d", &T);
for (int cas = ; cas <= T; ++cas) {
int n;
scanf("%d", &n);
std::vector<int> a(n);
for (int i = ; i < n; ++i) {
scanf("%d", &a[i]);
} std::vector<int> left(n, -), right(n, -), stk(n), parent(n, -);
for (int i = , top = ; i < n; ++i) {
int last = -;
while (top && a[i] > a[stk[top - ]]) {
last = stk[--top];
}
if (top) {
right[stk[top - ]] = i;
parent[i] = stk[top - ];
}
left[i] = last;
if (last != -) parent[last] = i;
stk[top++] = i;
} std::vector<int> inv(n + , );
for (int i = ; i < n + ; ++i) {
inv[i] = int64(mod - mod / i) * inv[mod % i] % mod;
} using pii = std::pair<int, int>;
{
std::vector<pii> a(n), b(n);
std::queue<int> queue;
std::vector<int> cnt(n);
for (int i = ; i < n; ++i) {
a[i] = b[i] = {inv[], };
if (left[i] == - && right[i] == -) {
queue.push(i);
}
cnt[i] = (left[i] != -) + (right[i] != -);
}
while (!queue.empty()) {
int u = queue.front(); queue.pop();
pii res = {(int64)a[u].first * inv[a[u].second] % mod * b[u].first % mod * inv[b[u].second] * % mod, a[u].second + b[u].second + };
int p = parent[u];
if (p == -) {
printf("%d\n", res.first);
break;
}
if (cnt[p] == ) a[p] = res;
else if (cnt[p] == ) b[p] = res;
--cnt[p];
if (cnt[p] == ) queue.push(p);
}
}
}
return ;
}

讲道理,还是有点不太清楚,还不熟练,多学习一下。

溜了。。。

HDU 6305.RMQ Similar Sequence-笛卡尔树+数学期望 (2018 Multi-University Training Contest 1 1008)的更多相关文章

  1. HDU - 6305 RMQ Similar Sequence(笛卡尔树)

    http://acm.hdu.edu.cn/showproblem.php?pid=6305 题目 对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0 ...

  2. hdu 6305 RMQ Similar Sequence——概率方面的思路+笛卡尔树

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6305 看题解,得知: 0~1内随机取实数,取到两个相同的数的概率是0,所以认为 b 序列是一个排列. 两个 ...

  3. [乱搞]hdu 6406 Taotao picks apples 笛卡尔树+倍增

    题目链接 Problem Description There is an apple tree in front of Taotao's house. When autumn comes, n app ...

  4. 2018 Multi-University Training Contest 1 H - RMQ Similar Sequence(HDU - 6305 笛卡尔树)

    题意: 对于一个序列a,构造一个序列b,使得两个序列,对于任意的区间 [l, r] 的区间最靠近左端点的那个最大值的位置,并且序列 b 满足 0 < bi < 1. 给定一个序列 a ,求 ...

  5. [模板] 笛卡尔树 && RMQ

    话说我noip之前为什么要学这种东西... 简介 笛卡尔树(Cartesian Tree) 是一种二叉树, 且同时具有以下两种性质: 父亲节点的值大于/小于子节点的值; 中序遍历的结果为原序列. 笛卡 ...

  6. hdu 1506 Largest Rectangle in a Histogram——笛卡尔树

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1506 关于笛卡尔树的构建:https://www.cnblogs.com/reverymoon/p/952 ...

  7. HDU - 1506 Largest Rectangle in a Histogram (单调栈/笛卡尔树)

    题意:求一个直方图中最大矩形的面积. 很经典的一道问题了吧,可以用单调栈分别求出每个柱子左右两边第一个比它低的柱子(也就相当于求出了和它相连的最后一个比它高的柱子),确定每个柱子的左右边界,每个柱子的 ...

  8. HDU 1506 Largest Rectangle in a Histogram(单调栈、笛卡尔树)

    题意:给定n个连续排列的矩形的高,矩形的宽都为1.问最大矩形覆盖. 例如:n = 7,h[i] = (2 1 4 5 1 3 3),最大覆盖为8. Sample Input 7 2 1 4 5 1 3 ...

  9. 笛卡尔树--牛客第四场(sequence)

    思路: O(n)建一颗笛卡尔树,再O(n)dfs向上合并答案就行了. #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include &l ...

随机推荐

  1. Django 2.0官方文档中文 总索引

    Django 2.0官方文档中文 渣翻 总索引 翻译 2017年12月08日 11:19:1 官方原文: https://docs.djangoproject.com/en/2.0/ 当前翻译版本:  ...

  2. 有关ViewFlipper的使用及设置动画效果的讲解

    说到左右滑动,其实实现左右滑动的方式很多,有ViewPaer,自定义实现Viewgroup,gallery等都可以达到这种效果.这里做下ViewFliper实现左右滑动的效果. 会用到以下的技术: 1 ...

  3. scp 将数据从一台linux服务器复制到另一台linux服务器

    原文地址:http://www.cnblogs.com/peida/archive/2013/03/15/2960802.html  完整内容参考原文! scp 是secure copy的简写,用于在 ...

  4. 把SVN版本控制讲给 非IT同事 听

    场景: 什么是版本: 什么是版本控制: 为什么要用版本控制: 推荐使用SVN: 如何快速理解SVN: SVN简单使用:

  5. python学习总结---文件操作

    # 文件操作 ### 目录管理(os) - 示例 ```python # 执行系统命令 # 清屏 # os.system('cls') # 调出计算器 # os.system('calc') # 查看 ...

  6. (转\整)UE4游戏优化 多人大地型游戏的优化(一)游戏线程的优化

    施主分享随缘,评论随心,@author:白袍小道 小道暗语: 1.因为小道这里博客目录没自己整,暂时就用随笔目录结构,所以二级目录那啥就忽略了.标题格式大致都是(原or转) 二级目录 (标题) 2.因 ...

  7. Android数据储存之SharedPreferences总结

    写在前面:本文是我参考李刚老师的<疯狂Android讲义>以及API所写的读书笔记,在此表示感谢,本人小白,如有错误敬请指教. SharedPreferences的使用背景: 有时候,应用 ...

  8. python获取文件夹下数量

    import os totalSize = 0 fileNum = 0 dirNum = 0 def visitDir(path): global totalSize global fileNum g ...

  9. CentOS Linux上搭建PPPoE服务器及拨号设置

    CentOS Linux上搭建PPPoE服务器及拨号设置 搭建PPPoE,成功了的话,就觉得超级简单,在CentOS Linux更是5步左右就能搞定. 1.安装pppoe,安装完成后,会有pppoe- ...

  10. [CF482B]Interesting Array

    题目大意:构造一个序列$S$,有$m$条限制,每条为$l\;r\;q$,表示$\&_{i=l}^r S_i=q$ 题解:每条限制就把$[l,r]$内的数或上$q$,最后判断就行了 卡点:我又写 ...