bzoj4574: [Zjoi2016]线段树
爆了一天。。。我还是太菜
#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; }
pain and happy in the cruel world.