bzoj 4574: [Zjoi2016]线段树

Description

小Yuuka遇到了一个题目:有一个序列a_1,a_2,?,a_n,q次操作,每次把一个区间内的数改成区间内的最大值,问
最后每个数是多少。小Yuuka很快地就使用了线段树解决了这个问题。于是充满智慧的小Yuuka想,如果操作是随机
的,即在这q次操作中每次等概率随机地选择一个区间l,r,然后将这个区间内的数改成区间内最大
值(注意这样的区间共有(n(n+1))/2个),最后每个数的期望大小是多少呢?小Yuuka非常热爱随机,所以她给出
的输入序列也是随机的(随机方式见数据规模和约定)。对于每个数,输出它的期望乘((n(n+1))/2)^q再对10^9+7取模的值。

Solution

考虑每一个位置最后会变成的值,这个不好算
考虑每一个位置作为最大值可以影响到的范围
枚举每一个点作为最大值 (x), (DP) 算贡献
(f[k][i][j]) 表示前 (k) 次操作, ([i,j]) 的最大值小于等于 (x) 的方案数
(i-1),(j+1) 比区间最大值大的,每次选的区间包含这两个位置就会缩短区间,否则不变
分区间长度缩短和不变两种写就好了
最后求出的是小于等于 (x) 的方案数,容斥一下得到等于 (x) 的方案数
随机数据下,复杂度期望 (O(q*n^2))

#include<bits/stdc++.h>
#define RG register
using namespace std;
const int N=405,mod=1e9+7;
int n,m,a[N],g[N],b[N],f[2][N][N],s[N][N];
inline void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
inline void solve(int l,int r,int p){
	for(int i=l;i<=r;i++)
		for(int j=l;j<=r;j++)f[0][i][j]=f[1][i][j]=0;
	bool t=0;
	f[0][l][r]=1;
	for(int P=1;P<=m;P++,t^=1){
		for(int i=l;i<=r;i++){
			int sum=0;
			for(RG int j=r;j>=i;j--){
				int w=f[t][i][j];
				add(f[t^1][i][j],sum);
				sum=(sum+1ll*w*(n-j))%mod;
			}
		}
		for(int j=l;j<=r;j++){
			int sum=0;
			for(RG int i=l;i<=j;i++){
				int w=f[t][i][j];f[t][i][j]=0;
				add(f[t^1][i][j],sum);
				add(f[t^1][i][j],1ll*w*(1ll*g[i-1]+g[j-i+1]+g[n-j])%mod);
				sum=(sum+1ll*w*(i-1))%mod;
			}
		}
	}
	for(int i=l;i<=r;i++)
		for(int j=i;j<=r;j++)
			if(f[t][i][j])
				for(RG int k=i;k<=j;k++)s[k][a[p]]=(s[k][a[p]]+f[t][i][j])%mod;
}
int main(){
	freopen("pp.in","r",stdin);
	freopen("pp.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),g[i]=i*(i+1)>>1,b[i]=a[i];
	sort(b+1,b+n+1);
	int tp=unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+tp+1,a[i])-b;
	for(int i=1;i<=n;i++){
		int l=i,r=i;
		while(l>1 && a[l-1]<=a[i])l--;
		while(r<n && a[r+1]<=a[i])r++;
		solve(l,r,i);
	}
	for(int i=1;i<=n;i++){
		int ans=0;
		for(int j=1;j<=tp;j++)
			if(s[i][j]){
				for(int k=1;k<j;k++)s[i][j]=(s[i][j]-s[i][k]+mod)%mod;
				ans=(ans+1ll*b[j]*s[i][j])%mod;
			}
		printf("%d ",ans);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8991291.html