您的位置:首页 > 其它

BZOJ 4574: [Zjoi2016]线段树/UOJ #196. 【ZJOI2016】线段树 dp

2017-09-11 09:42 513 查看

4574: [Zjoi2016]线段树

Time Limit: 30 Sec Memory Limit: 256 MB

Submit: 357 Solved: 117

[Submit][Status][Discuss]

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

我真是十分擅长转载啊

这里有一份巨快的代码

这是一份在bzoj光荣T掉的代码

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>

using namespace std;

typedef long long ll;

inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(ll x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=410,mod=int(1e9)+7;

int n,q,L,R,rank
,a
,pos
;

ll f[2]

,A

,sum

,cnt
;

void DP(int x)
{
register int i,j,k;
for(i=L;i<=R;++i)for(j=L;j<=R;++j)f[0][i][j]=f[1][i][j]=0;
f[0][L][R]=1;
for(k=1;k<=q;++k)
{
ll val=0;
for(i=L;i<=R;++i)
{
val=0;
for(j=R;j>=i;j--)
{f[k&1][i][j]=val;val=(val+f[(k-1)&1][i][j]*(n-j))%mod;}
}
for(j=L;j<=R;++j)
{
val=0;
for(i=L;i<=j;++i)
{f[k&1][i][j]=(f[k&1][i][j]+val)%mod;val=(val+f[(k-1)&1][i][j]*(i-1))%mod;}
}
for(i=L;i<=R;++i)for(j=i;j<=R;++j)
f[k&1][i][j]=(f[k&1][i][j]+f[(k-1)&1][i][j]*A[i][j])%mod;
}
for(i=L;i<=R;++i)
{
ll val=0;
for(j=R;j>=i;j--)
{
(val+=f[q&1][i][j])%=mod;
(sum[j][rank[x]]+=val)%=mod;
}
}
}

inline bool cmp(int x,int y){return a[x]<a[y];}

int main()
{
n=read();q=read();
register int i,j,k;
for(i=1;i<=n;++i)a[i]=read(),pos[i]=i;
sort(pos+1,pos+1+n,cmp);
for(i=1;i<=n;++i)rank[pos[i]]=i,cnt[i]=(i*i+i)/2;
for(i=1;i<=n;++i)for(j=i;j<=n;++j)A[i][j]=cnt[i-1]+cnt[n-j]+cnt[j-i+1];
for(i=1;i<=n;++i)
{
L=R=i;
while(L&&a[L]<=a[i])L--;L++;
while(R<=n&&a[R]<=a[i])R++;R--;
DP(i);
}
ll ans;
for(i=1;i<=n;++i)
{
ans=0;
for(j=1;j<=n;++j)
{
if(sum[i][j]==0)continue;
for(k=1;k<j;++k)sum[i][j]-=sum[i][k];
sum[i][j]%=mod;(sum[i][j]+=mod)%=mod;
ans+=1ll*a[pos[j]]*sum[i][j];ans%=mod;
}
ans%=mod;(ans+=mod)%=mod;
print(ans);if(i<n)putchar(' ');
}
puts("");
return 0;
}
/*
5 5
1 5 2 3 4

3152671 3796875 3692207 3623487 3515626
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: