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

bzoj4574: [Zjoi2016]線段樹

爆了一天。。。我還是太菜

ORZ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'
0'&&ch>'9'){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void write(LL x) { if(x<0)putchar('-'),x=-x; if(x>=10)write(x/10); putchar(x%10+'0'); } int n,m; int a[410],lslen,ls[410],L[410],R[410]; LL f[
2][410][410];//什麼時間,區間之中的點都以當前權值為最大值方案數 LL g[410][410];//第i個位置變成了以排名<=j的權值為最大值的方案數 LL FF[410],c[410][410]; void DP(int p) { int now=0; LL s; memset(f,0,sizeof(f));f[now][L[p]][R[p]]=1; for(int k=1;k<=m;k++) { now^=1; for(int i=L[p];i<=R[p];i++) { s
=0; for(int j=R[p];j>=i;j--) f[now][i][j]=s, s+=f[now^1][i][j]*(n-j); } for(int j=L[p];j<=R[p];j++) { s=0; for(int i=L[p];i<=j;i++) f[now][i][j]+=s, s+=f[now^1][i][j]*(i-1); } for(int i=L[p];i<=R[p];i++) for(int j=i;j<=R[p];j++) f[now][i][j]+=f[now^1][i][j]*c[i][j], f[now][i][j]%=mod; } for(int i=L[p];i<=R[p];i++) { s=0; for(int j=R[p];j>=i;j--) s+=f[now][i][j], g[j][a[p]]=(g[j][a[p]]+s)%mod; } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); n=read(),m=read(); lslen=0; for(int i=1;i<=n;i++) a[i]=read(),ls[++lslen]=a[i]; sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; for(int i=1;i<=n;i++) a[i]=lower_bound(ls+1,ls+lslen+1,a[i])-ls; for(int i=1;i<=n;i++)FF[i]=(i*i+i)/2; for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) c[i][j]=FF[i-1]+FF[n-j]+FF[j-i+1]; for(int i=1;i<=n;i++) { L[i]=1;for(int j=i-1;j>=1;j--)if(a[i]<a[j]){L[i]=j+1;break;} R[i]=n;for(int j=i+1;j<=n;j++)if(a[i]<a[j]){R[i]=j-1;break;} DP(i); } LL ans; for(int i=1;i<=n;i++) { ans=0; for(int j=1;j<=lslen;j++) { if(g[i][j]==0)continue; for(int k=1;k<j;k++)g[i][j]-=g[i][k]; while(g[i][j]<0)g[i][j]+=mod; ans+=ls[j]*g[i][j],ans%=mod; } write(ans),putchar(' '); } //容斥 return 0; }