1. 程式人生 > >bzoj4574 [Zjoi2016]線段樹

bzoj4574 [Zjoi2016]線段樹

queue space class cnblogs 選擇 cstring char net long long

Description

小Yuuka遇到了一個題目:有一個序列a_1,a_2,?,a_n,q次操作,每次把一個區間內的數改成區間內的最大值,問最後每個數是多少。小Yuuka很快地就使用了線段樹解決了這個問題。於是充滿智慧的小Yuuka想,如果操作是隨機的,即在這q次操作中每次等概率隨機地選擇一個區間[l,r](1≤l≤r≤n),然後將這個區間內的數改成區間內最大值(註意這樣的區間共有(n(n+1))/2個),最後每個數的期望大小是多少呢?小Yuuka非常熱愛隨機,所以她給出的輸入序列也是隨機的(隨機方式見數據規模和約定)。對於每個數,輸出它的期望乘((n(n+1))/2)^q再對10^9+7取模的值。

Input

第一行包含2個正整數n,q,表示序列裏數的個數和操作的個數。接下來1行,包含n個非負整數a1,a2...an。N<=400,Q<=400

Output

輸出共1行,包含n個整數,表示每個數的答案

Sample Input

5 5
1 5 2 3 4

Sample Output

3152671 3796875 3692207 3623487 3515626

正解:$dp$。

這道題還是太鬼了,我直接給一個博客吧:http://blog.csdn.net/qq_34637390/article/details/51290087

根本就不想寫題解了。。

 1
//It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12
#include <set> 13 #define rhl (1000000007) 14 #define N (410) 15 #define il inline 16 #define RG register 17 #define ll long long 18 19 using namespace std; 20 21 int cal[N][N],a[N],s[N],rk[N],cnt[N],n,q; 22 ll f[2][N][N],sum[N][N],ans; 23 24 il int gi(){ 25 RG int x=0,q=1; RG char ch=getchar(); 26 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 27 if (ch==-) q=-1,ch=getchar(); 28 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 29 return q*x; 30 } 31 32 il int cmp(const int &x,const int &y){ return a[x]<a[y]; } 33 34 il void solve(RG int l,RG int r,RG int now){ 35 for (RG int i=l;i<=r;++i) 36 for (RG int j=l;j<=r;++j) f[0][i][j]=f[1][i][j]=0; 37 f[0][l][r]=1; RG ll res; 38 for (RG int k=1,cur=1,p=0;k<=q;++k,p=cur,cur^=1){ 39 for (RG int j=l;j<=r;++j){ 40 res=0; 41 for (RG int i=l;i<=j;++i) 42 f[cur][i][j]=res,res+=f[p][i][j]*(ll)(i-1); 43 } 44 for (RG int i=l;i<=r;++i){ 45 res=0; 46 for (RG int j=r;j>=i;--j){ 47 (f[cur][i][j]+=res+f[p][i][j]*(ll)cal[i][j])%=rhl; 48 res+=f[p][i][j]*(ll)(n-j); 49 } 50 } 51 } 52 RG int cur=q&1; 53 for (RG int i=l;i<=r;++i){ 54 res=0; 55 for (RG int j=r;j>=i;--j) 56 res+=f[cur][i][j],(sum[j][rk[now]]+=res)%=rhl; 57 } 58 return; 59 } 60 61 int main(){ 62 #ifndef ONLINE_JUDGE 63 freopen("segment.in","r",stdin); 64 freopen("segment.out","w",stdout); 65 #endif 66 n=gi(),q=gi(); 67 for (RG int i=1;i<=n;++i) a[i]=gi(),s[i]=i,cnt[i]=i*(i+1)>>1; 68 sort(s+1,s+n+1,cmp); for (RG int i=1;i<=n;++i) rk[s[i]]=i; 69 for (RG int i=1;i<=n;++i) 70 for (RG int j=i;j<=n;++j) cal[i][j]=cnt[i-1]+cnt[n-j]+cnt[j-i+1]; 71 for (RG int i=1,l,r;i<=n;++i){ 72 l=r=i; while (l && a[l]<=a[i]) --l; 73 while (r<=n && a[r]<=a[i]) ++r; solve(l+1,r-1,i); 74 } 75 for (RG int i=1;i<=n;++i){ 76 ans=0; 77 for (RG int j=1;j<=n;++j){ 78 if (!sum[i][j]) continue; 79 for (RG int k=1;k<j;++k) (sum[i][j]-=sum[i][k])%=rhl; 80 (ans+=sum[i][j]*(ll)a[s[j]])%=rhl; 81 } 82 (ans+=rhl)%=rhl; 83 if (i!=n) printf("%lld ",ans); else printf("%lld",ans); 84 } 85 return 0; 86 }

bzoj4574 [Zjoi2016]線段樹