bzoj4574:Zjoi2016线段树 dp

传送门

题解传送门

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int N=410;
#define mo 1000000007
int n,q,x[N],y[N],rank[N];
int cnt[N],A[N][N];long long dp[2][N][N],sum[N][N];

bool mycmp(int a,int b) { return x[a]<x[b]; }

void init() {
    scanf("%d%d",&n,&q);
      for(int i=1;i<=n;i++)scanf("%d",&x[i]);
      for(int i=1;i<=n;i++)y[i]=i;
      sort(y+1,y+1+n,mycmp);
      for(int i=1;i<=n;i++)rank[y[i]]=i;
      return ;
}

#define dp(i,j,k) dp[(i)%2][j][k]
void solve(int l,int r,int now) {
    for(int i=l;i<=r;i++) for(int j=l;j<=r;j++)dp(0,i,j)=dp(1,i,j)=0;
      dp(0,l,r)=1;
      long long ct;
      for(int k=1;k<=q;k++) {
        for(int i=l;i<=r;i++) {
              ct=0;
              for(int j=r;j>=i;j--) {
                dp(k,i,j)=ct; ct=(ct+dp(k-1,i,j)*(n-j))%mo;
              }
        }
            for(int j=l;j<=r;j++) {
              ct=0;
              for(int i=l;i<=j;i++) {
                dp(k,i,j)=(dp(k,i,j)+ct)%mo; ct=(ct+dp(k-1,i,j)*(i-1));
              }
        }
        for(int i=l;i<=r;i++) {
              for(int j=i;j<=r;j++) {
                    dp(k,i,j)=(dp(k,i,j)+(dp(k-1,i,j)*A[i][j]))%mo;
            }
           }
      }
    for(int i=l;i<=r;i++) {
           ct=0;
        for(int j=r;j>=i;j--) {
              ct=(ct+dp(q,i,j));
              sum[j][rank[now]]=(ct+sum[j][rank[now]])%mo;
        }
      }
      return ;
}

int main() {
#ifdef DEBUG
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    init();
    int l,r;
    for(int i=1;i<=n;i++)  cnt[i]=i*(i+1)/2;
    for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) A[i][j]=cnt[i-1]+cnt[n-j]+cnt[j-i+1];
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++) {
           l=r=i;
        while(l && x[l]<=x[i])l--; while(r<=n && x[r]<=x[i])r++;
        solve(l+1,r-1,i);
    }
    int ans;
    for(int i=1;i<=n;i++) {
        ans=0;
        for(int j=1;j<=n;j++) {
              if(!sum[i][j])continue;
              for(int u=1;u<j;u++)sum[i][j]=(sum[i][j]-sum[i][u])%mo;
              ans=((long long)ans+1ll*x[y[j]]*sum[i][j])%mo;
        }
        ans=(ans+mo)%mo;
        if(i!=n) printf("%d ",ans);else printf("%d",ans);
      }
  
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/Achenchen/p/8551111.html