HDU 6305 2018 HDU多校赛第一场 RMQ Similar Sequence(笛卡尔树+手工栈)

RMQ Similar Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 255535/255535 K (Java/Others)
Total Submission(s): 835    Accepted Submission(s): 255


 

Problem Description

Chiaki has a sequence A={a1,a2,…,an} . Let RMQ(A,l,r) be the minimum i (l≤i≤r ) such that ai is the maximum value in al,al+1,…,ar .

Two sequences A and B are called \textit{RMQ Similar}, if they have the same length n and for every 1≤l≤r≤n , RMQ(A,l,r)=RMQ(B,l,r) .

For a given the sequence A={a1,a2,…,an} , define the weight of a sequence B={b1,b2,…,bn} be ∑i=1nbi (i.e. the sum of all elements in B ) if sequence B and sequence A are RMQ Similar, or 0 otherwise. If each element of B is a real number chosen independently and uniformly at random between 0 and 1 , find the expected weight of B .

 

Input

There are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤106 ) -- the length of the sequence.
The second line contains n integers a1,a2,…,an (1≤ai≤n ) denoting the sequence.
It is guaranteed that the sum of all n does not exceed 3×106 .

 

Output

For each test case, output the answer as a value of a rational number modulo 109+7 .
Formally, it is guaranteed that under given constraints the probability is always a rational number pq (p and q are integer and coprime, q is positive), such that q is not divisible by 109+7 . Output such integer a between 0 and 109+6 that p−aq is divisible by 109+7 .

 

Sample Input

 

3 3 1 2 3 3 1 2 1 5 1 2 3 2 1

 

Sample Output

 

250000002 500000004 125000001

 

Source

2018 Multi-University Training Contest 1

大致题意:给你一个串A,定义RMQ相似串为,对任意区间[L,R],两个串RMQ所在位置相同。告诉你B串中每个元素服从于[0,1]上相互独立的均匀分布。B的权值定义为,当B与A串RMQ相似时,权值为所有元素之和,否则为0。现在问你B串的期望权值是多少。

首先,看到这种RMQ然后两个串要相似的,很容易想到用笛卡尔树。所谓笛卡尔树,就是说,对于一个区间,我选择RMQ作为根,然后把区间分为两部分。这两部分再次分别用RMQ作为根继续划分,直到划分到单位区间。

这题的话求一个期望,显然只需要关心那些权值不为0的。B与A串RMQ相似,有一些条件,即每一个点是以它为根的子树中所有点对应数字中最大的一个。那么对于这个点来说,满足要求的概率就是1/size[i]。总的来说就是\prod \frac{1}{size[i]}。然后再看权值和,由于每个元素相互独立,且服从于[0,1]上的均匀分布,所以显然权值和的期望就是\frac{n}{2},于是这题的答案就是\frac{n}{2*\prod size[i]}具体在实现的时候,由于本题1e6的数据范围,直接递归求解回爆栈,所以要用手工栈模拟的方法。具体见代码:

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
#define N 1000100
using namespace std;

struct PII
{
    int first,second;

    bool operator<(const PII &a) const
    {
        return first==a.first?second>a.second:first<a.first;
    }
};

int T,stk1[N],stk2[N];
LL inv[N],ans;
PII a[22][N];
int v[N];

struct ST
{

    void build(int n)
    {
        int t=31-__builtin_clz(n);
        for (int j=1;j<=t;j++)
        {
            for (int i=1;i<=n;i++)if (i+(1<<(j-1)) <=n)
            {
                a[j][i]=max(a[j-1][i],a[j-1][i+(1<<(j-1))]);
            }
        }
    }

    PII getmax(int j,int k)
    {
        if (j==k) return a[0][j];
        else
        {
            int t=31-__builtin_clz(k-j);
            return max(a[t][j],a[t][k-(1<<t)+1]);
        }
    }

} seg;

void build(int l,int r)
{
    int top=0;
    stk1[++top]=l; stk2[top]=r; v[top]=0;
    while(top)
    {
        l=stk1[top]; r=stk2[top]; v[top]++;
        if (v[top]>2) {top--;continue;}
        if (v[top]==2)
        {
            int x=seg.getmax(l,r).second;
            if (x+1<r) stk1[++top]=x+1,stk2[top]=r,v[top]=0;
        } else
        {
            ans=ans*inv[r-l+1]%mod;
            int x=seg.getmax(l,r).second;
            if (l<x-1) stk1[++top]=l,stk2[top]=x-1,v[top]=0;
        }
    }

}

void init()
{
    inv[0]=inv[1]=1;
    for(int i=2;i<N;i++)
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}


int main ()
{
    init();
    scanf("%d",&T);
    while(T--)
    {
        int n; ans=1;
        scanf("%d",&n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d",&a[0][i].first);
            a[0][i].second=i;
        }
        seg.build(n);
        build(1,n);
        printf("%I64d\n",ans*inv[2]%mod*n%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013534123/article/details/81194666