luogu P3352 [ZJOI2016]线段树
题面传送门
直接看这个区间取max感觉很离谱,可以考虑差分变成算一个数大于等于某个数\(x\)的方案数。、
固定一个位置,然后发现如果将大于等于\(x\)的数置为\(1\),小于等于\(x\)的数置为\(0\),则两端点的\(1\)随着操作的增加是单调往里走的。
具体的,设\(dp_{i,l,r}\)表示在第\(i\)次操作后,\([l,r]\)区间的两端点为\(1\),且中间全部为0的方案数。
容易得到转移:\(dp_{i,l,r}=\sum\limits_{h=1}^{l-1}{dp_{i-1,i,r}\times i}+\sum\limits_{h=r+1}^{n}{dp_{i-1,l,h}\times (n-h+1)}\),这个东西显然可以前缀和转移,时间复杂度\(O(n^2q)\),加上外层的枚举,时间复杂度\(O(n^3q)\)
发现对于每个数的dp转移都是一样的,所以可以整体dp,就是把这些都放在一起dp。发现实际上区间不交,所以是可以的,时间复杂度降为\(O(n^2q)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define U unsigned int
#define db double
#define lb long db
#define N (400+5)
#define M (220+5)
#define K (650+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,z,Ne,La,A[N],B[N];ll Po,dp[2][N][N],Invn,Q1[N][N],Q2[N][N],T[N];
I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}
int main(){
freopen("1.in","r",stdin);
int i,j,h,x,y;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%d",&A[i]),B[i]=A[i];for(Po=i=1;i<=m;i++) Po=Po*n*(n+1)/2%mod;sort(B+1,B+n+1);
for(i=1;i<=n;i++){
for(x=0;x<=n+1;x=y){
for(y=x+1;y<=n;y++) if(A[y]>=B[i]) break;dp[0][x][y]+=B[i]-B[i-1];for(j=x;j<y;j++) T[j]+=Po*(B[i]-B[i-1])%mod;
}
}
for(i=0;i<m;i++){Ne=i&1;La=Ne^1;Me(dp[La],0);
for(x=0;x<n;x++) for(y=n+1;y>=x+2;y--) x&&(Q1[x][y]+=Q1[x-1][y]),Q2[x][y]+=Q2[x][y+1],dp[Ne][x][y]=(dp[Ne][x][y]+Q1[x][y]+Q2[x][y])%mod;Me(Q1,0);Me(Q2,0);
for(x=0;x<n;x++){
for(y=x+2;y<=n+1;y++) {
dp[La][x][y]=(dp[Ne][x][y]*(x*(x+1)/2+(n-y+1)*(n-y+2)/2+(y-x-1)*(y-x)/2)+dp[La][x][y])%mod;
Q1[x+1][y]=(Q1[x+1][y]+dp[Ne][x][y]*x)%mod;Q2[x][y-1]=(Q2[x][y-1]+dp[Ne][x][y]*(n+1-y))%mod;
}
}
} Ne=m&1;La=Ne^1;for(x=0;x<n;x++) for(y=n+1;y>=x+2;y--) x&&(Q1[x][y]+=Q1[x-1][y]),Q2[x][y]+=Q2[x][y+1],dp[Ne][x][y]=(dp[Ne][x][y]+Q1[x][y]+Q2[x][y])%mod;
for(i=1;i<=n;printf("%lld ",(T[i]%mod+mod)%mod),i++)for(x=0;x<i;x++) for(y=i+1;y<=n+1;y++) T[i]-=dp[Ne][x][y];
/*for(i=1;i<=n;i++){
for(j=1;j<=n;j++){for(x=i;x;x--) if(A[x]>=B[j]) break;for(y=i;y<=n;y++) if(A[y]>=B[j]) break;T[i]+=(B[j]-B[j-1])*Po[m]%mod;dp[0][x][y]+=B[j]-B[j-1];}
for(j=0;j<m;j++){Ne=j&1;La=Ne^1;
for(x=0;x<i;x++) for(y=n+1;y>i;y--) Q1[x][y]=Q2[x][y]=0;
}Ne=m&1;La=Ne^1;for(x=0;x<i;x++) for(y=n+1;y>i;y--) x&&(Q1[x][y]+=Q1[x-1][y]),Q2[x][y]+=Q2[x][y+1],dp[Ne][x][y]=(dp[Ne][x][y]+Q1[x][y]+Q2[x][y])%mod,T[i]-=(dp[Ne][x][y]);printf("%lld ",(T[i]%mod+mod)%mod);
}*/
}