[线段树性质][计数] SegmentTree 题解

在这里插入图片描述
在这里插入图片描述
本题说是求概率,实际上由于 [ l , r ] [l,r] [l,r] 总数一定,要求的就是不合法的 [ l , r ] [l,r] [l,r] 的情况数

何时不合法?

首先我们会发现,只有 query 函数递归到叶子时,由于上面的 define,才可能导致 a a a 数组越界而 RE

注意这里为什么说 “可能” ,考虑下面这种情况

在这里插入图片描述
注意到达到 9 9 9 号点时, l s = 18 , r s = 19 ls = 18 , rs = 19 ls=18,rs=19 ,而 a a a 数组范围是 [ 0 , 23 ] [0,23] [0,23] ,所以没什么问题。但是到 12 , 13 12,13 12,13 号点就会错

考虑怎样的区间会访问到 12 , 13 12,13 12,13 这样的叶子

打表发现,当 RE 叶子 x x x ( x 代表原数组中表示的下标 ) 是一个左儿子时,当且仅当 l ≤ r = x l\leq r = x lr=x 的区间会访问到,共 x x x 个区间

右儿子时,则需要满足 x = l ≤ r x=l\leq r x=lr ,共 n − x + 1 n-x+1 nx+1

那么问题很清晰了,直接在线段树上模拟这个过程,递归到叶子时如果发现这是一个 RE 叶子,根据左右情况累加到 a n s ans ans

需要注意的一点是:一个区间 如果左右端点都是 RE 叶子的话 会被重复算,容斥一下

一组数据 RE 的概率是 a n s n ( n + 1 ) / 2 \Large\frac{ans}{n(n+1)/2} n(n+1)/2ans ,那么 T 组数据全 AC 的概率就是 Π ( 1 − a n s i n i ( n i + 1 ) / 2 ) \large\Pi(1-\frac{ans_i}{n_i(n_i+1)/2}) Π(1ni(ni+1)/2ansi)

#include<bits/stdc++.h>
using namespace std ;
#define int long long

typedef long long LL ;
const int N = 1e5 + 100 ;
const LL mod = 1e9 + 7 ;
/*性质:若访问到的越界叶子x是一个左儿子,则所有 [l,x] l<=x 为不合法的询问
 若为右儿子,则所有 [x,r] r>=x 不合法 
*/ 

LL ksm( LL a , LL b )
{
	LL res = 1 , t = a % mod ;
	while( b ) {
		if( b&1 ) res = res * t % mod ;
		b = b >> 1 ;
		t = t * t % mod ;
	}
	return res ;
}

int T ;
int n , q ;
LL cnt , ans , R = 1 ;
void build( int p , int l , int r )
{
	if( l == r ) {
		if( p*2+1 >= 4*n ) { // 越界叶子 
			if( p&1 ) {
				ans += n-l+1 ;
				cnt ++ ;
			}
			else {/*左*/
				ans += l-cnt ;
			}
		}
		return ;
	}
	int mid = ( l + r ) >> 1 ;
	build( p<<1 , l , mid ) ;
	build( p<<1|1 , mid+1 , r ) ;
}
 
signed main()
{
	scanf("%lld" , &T ) ;
	while( T -- ) {
		ans = cnt = 0 ;
		scanf("%lld%lld" , &n , &q ) ;
		build( 1 , 1 , n ) ;
		LL tot = 1LL*n*(n+1)%mod ;
		R = R * ksm( ((tot-2LL*ans)%mod+mod)%mod*ksm( tot , mod-2 )%mod , q ) % mod ;
	}
	printf("%lld" , R ) ;
  	return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值