洛谷P3352 [ZJOI2016]线段树

P3352 [ZJOI2016]线段树

(^ w ^)

题目描述
小Yuuka遇到了一个题目:有一个序列a_1,a_2,?,a_n,q次操作,每次把一个区间内的数改成区间内的最大值,问最后每个数是多少。小Yuuka很快地就使用了线段树解决了这个问题。

于是充满智慧的小Yuuka想,如果操作是随机的,即在这q次操作中每次等概率随机地选择一个区间l,r,然后将这个区间内的数改成区间内最大值(注意这样的区间共有(n(n+1))/2个),最后每个数的期望大小是多少呢?小Yuuka非常热爱随机,所以她给出的输入序列也是随机的(随机方式见数据规模和约定)。对于每个数,输出它的期望乘((n(n+1))/2)q再对109+7取模的值。

输入输出格式
输入格式:
第一行包含2个正整数n,q,表示序列里数的个数和操作的个数。接下来1行,包含n个非负整数a1,a2…an。N<=400,Q<=400

输出格式:
输出共1行,包含n个整数,表示每个数的答案

输入输出样例
输入样例#1:

5 5
1 5 2 3 4

输出样例#1:

3152671 3796875 3692207 3623487 3515626

题解

换而言之就是求每个点所有区间组合之后结果之和。

我们注意到这显然是一个dp题,所以要思考一个状态之和。

  f j , i , x , y \ f_{j,i,x,y}  fj,i,x,y表示进行   i \ i  i此操作后,区间   [ x , y ] \ [x,y]  [x,y]内,所有元素   ≤ j \ \le j  j   a y + 1 , a x − 1 ≥ j \ a_{y+1},a_{x-1} \ge j  ay+1,ax1j的方案数,   g i , j \ g _{i,j}  gi,j表示不横跨   i \ i  i   j \ j  j的区间的方案数。
我们可得一下dp式。
f s , i , x , y = f s , i − 1 , x , y ⋅ g x , y + ∑ j = 1 y − 1 f s , i − 1 , j , y ⋅ ( j − 1 ) + ∑ k = x + 1 n f s , i − 1 , x , k ⋅ ( n − k ) g x , y = x ( x − 1 ) 2 + ( y − x + 1 ) ( y − x + 2 ) 2 + ( n − y ) ( n − y + 1 ) 2 f_{s,i,x,y}=f_{s,i-1,x,y} \cdot g_{x,y} + \sum_{j=1}^{y-1} f_{s,i-1,j,y} \cdot (j-1) +\sum_{k=x+1}^{n} f_{s,i-1,x,k} \cdot (n-k) \\ g_{x,y}= \frac{x(x-1)}{2} + \frac{(y-x+1)(y-x+2)}{2} + \frac{(n-y)(n-y+1)}{2} fs,i,x,y=fs,i1,x,ygx,y+j=1y1fs,i1,j,y(j1)+k=x+1nfs,i1,x,k(nk)gx,y=2x(x1)+2(yx+1)(yx+2)+2(ny)(ny+1)

由此可以想到一个O(   n 4 \ n^{4}  n4)的算法:离散化之后枚举,这显然是不好过的然而有人卡过了。所以我们要像一个更优的算法。
我们发现第一维是固定的,式子也几乎不和第一维相关,所以我们改用其他状态。

  f i , x , y \ f_{i,x,y}  fi,x,y表示所有的第一维方案数之和。

转移式与之前完全相同:

f i , x , y = f i − 1 , x , y ⋅ g x , y + ∑ j = 1 y − 1 f i − 1 , j , y ⋅ ( j − 1 ) + ∑ k = x + 1 n f i − 1 , x , k ⋅ ( n − k ) g x , y = x ( x − 1 ) 2 + ( y − x + 1 ) ( y − x + 2 ) 2 + ( n − y ) ( n − y + 1 ) 2 f_{i,x,y}=f_{i-1,x,y} \cdot g_{x,y} + \sum_{j=1}^{y-1} f_{i-1,j,y} \cdot (j-1) +\sum_{k=x+1}^{n} f_{i-1,x,k} \cdot (n-k) \\ g_{x,y}= \frac{x(x-1)}{2} + \frac{(y-x+1)(y-x+2)}{2} + \frac{(n-y)(n-y+1)}{2} fi,x,y=fi1,x,ygx,y+j=1y1fi1,j,y(j1)+k=x+1nfi1,x,k(nk)gx,y=2x(x1)+2(yx+1)(yx+2)+2(ny)(ny+1)

复杂度O(   n 3 \ n^{3}  n3).

AC代码

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
int n,q,a[410];
long long f[2][410][410],sum1[2][410][410],sum2[2][410][410],g[410][410];
bool cmp(const int &x,const int &y)
{
    return a[x]<a[y];
}
int main()
{
    scanf("%d%d",&n,&q);
    int i=1,r=0,j=0,k=0;
    a[0]=2000000000;
    a[n+1]=2000000000;
    while(i<=n)
    {
        scanf("%d",&a[i]);
        ++i;
    }
    i=1;
    while(i<=n)
    {
        r=0;
        j=i;
        while(j<=n)
        {
            g[i][j]=i*(i-1)/2+(n-j)*(n-j+1)/2+(j-i+1)*(j-i+2)/2;
            r=max(r,a[j]);
            if((i==1)&&(j==n)) f[0][i][j]=r;
            else if((a[i-1]>r)&&(a[j+1]>r)) f[0][i][j]=(r-min(a[i-1],a[j+1])+mod)%mod;
            ++j;
        }
        ++i;
    }
    int now=1,last=0;
    i=1;
    while(i<=q)
    {
        j=1;
        while(j<=n)
        {
            k=n;
            while(k>=j)
            {
                sum2[last][j][k]=(sum2[last][j][k+1]+f[last][j][k]*(n-k))%mod;
                --k;
            }
            ++j;
        }
        j=1;
        while(j<=n)
        {
            k=j;
            while(k<=n)
            {
                sum1[last][j][k]=(sum1[last][j-1][k]+f[last][j][k]*(j-1))%mod;
                f[now][j][k]=(f[last][j][k]*g[j][k]+sum1[last][j-1][k]+sum2[last][j][k+1])%mod;
                ++k;
            }
            ++j;
        }
        now^=1;
        last^=1;
        ++i;
    }
    long long ss=0;
    i=1;
    while(i<=n)
    {
        ss=0;
        j=1;
        while(j<=i)
        {
            k=i;
            while(k<=n)
            {
                ss+=f[q&1][j][k];
                ss%=mod;
                ++k;
            }
            ++j;
        }
        printf("%lld ",ss);
        ++i;
    }
    return 0;
}
/*
1996年:东方灵异传(TOH1)
1997年:东方封魔录(TOH2)
1997年:东方梦时空(TOH3)
1998年:东方幻想乡(TOH4)
1998年:东方怪绮谈(TOH5)
2002年:东方红魔乡(TOH6)
2003年:东方妖妖梦(TOH7)
2004年:东方萃梦想(TOH7.5)
2004年:东方永夜抄(TOH8)
2005年:东方花映冢(TOH9)
2005年:东方文花帖(TOH9.5)
2007年:东方风神录(TOH10)
2008年:东方绯想天(TOH10.5)
2008年:东方地灵殿(TOH11)
2009年:东方星莲船(TOH12)
2009年:东方非想天则(TOH12.3)
2010年:东方文花帖DS(TOH12.5)
2010年:东方三月精(TOH12.8)
2011年:东方神灵庙(TOH13)
2013年:东方心绮楼(TOH13.5)
2013年:东方辉针城(TOH14)
2014年:弹幕天邪鬼(TOH14.3)
2014年:东方深秘录(TOH14.5)
2015年:东方绀珠传(TOH15)
2017年:东方凭依华(TOH15.5)
2017年:东方天空璋(TOH16)
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值