标签:merge int code 树形dp blog i++ 接下来 spl char
类似cf582E,先建出表达式树,然后树形dp+离散+min和max卷积的优化,复杂度为$o(nm|E|)$,无法通过
考虑我们仅关心于这$n$个数的大小关系,具体来说,假设给出的数组是$a_{i,j}$(其中$0\le i<m,1\le j\le n$),对于某一个$j$,将$a_{i,j}$从小到大排序后,依次是$a_{p_{i},j}$($0\le i<m$,$p_{i}$为$[0,m)$的一个排列)
暴力枚举$j$和$p_{i}$,接下来去统计答案不小于$a_{p_{i},j}$的方案数:
对于树形dp的状态上,我们仅需要记录小于$a_{p_{i},j}$和不小于$a_{p_{i},j}$的方案数,换言之是$o(1)$转移,但dp次数为$o(nm)$,因此总复杂度仍然是$o(nm|E|)$
但注意到,影响dp过程的只有对于每一个$i$,$[a_{i,j}\ge a_{p_{i},j}]$的值,不难发现至多$2^{m}$种,预处理出每一种值的结果,再枚举$j$和$p_{i}$求出是哪一种值即可
时间复杂度为$o(2^{m}|E|+nm)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50005 4 #define mod 1000000007 5 stack<int>st_op,st_num; 6 int V,n,m,p,ans,b[11][N],a[N],ls[N],rs[N],id[11],f[1<<10][N][2]; 7 char s[N]; 8 bool cmp(int x,int y){ 9 return b[x][p]>b[y][p]; 10 } 11 void merge(){ 12 a[++V]=st_op.top(); 13 st_op.pop(); 14 rs[V]=st_num.top(); 15 st_num.pop(); 16 ls[V]=st_num.top(); 17 st_num.pop(); 18 st_num.push(V); 19 } 20 void dfs(int k,int p){ 21 if ((!ls[k])&&(!rs[k])){ 22 f[p][k][((p&(1<<a[k]))>0)]=1; 23 return; 24 } 25 dfs(ls[k],p); 26 dfs(rs[k],p); 27 int s=(1LL*f[p][ls[k]][0]*f[p][rs[k]][1]+1LL*f[p][ls[k]][1]*f[p][rs[k]][0])%mod; 28 if (a[k]==0){ 29 f[p][k][0]=(1LL*f[p][ls[k]][0]*f[p][rs[k]][0]+s)%mod; 30 f[p][k][1]=1LL*f[p][ls[k]][1]*f[p][rs[k]][1]%mod; 31 } 32 if (a[k]==1){ 33 f[p][k][0]=1LL*f[p][ls[k]][0]*f[p][rs[k]][0]%mod; 34 f[p][k][1]=(1LL*f[p][ls[k]][1]*f[p][rs[k]][1]+s)%mod; 35 } 36 if (a[k]==2){ 37 f[p][k][0]=(2LL*f[p][ls[k]][0]*f[p][rs[k]][0]+s)%mod; 38 f[p][k][1]=(2LL*f[p][ls[k]][1]*f[p][rs[k]][1]+s)%mod; 39 } 40 } 41 int main(){ 42 scanf("%d%d",&n,&m); 43 for(int i=0;i<m;i++) 44 for(int j=1;j<=n;j++)scanf("%d",&b[i][j]); 45 scanf("%s",s); 46 int l=strlen(s),flag=0; 47 for(int i=0;i<l;i++) 48 if ((‘0‘<=s[i])&&(s[i]<=‘9‘)){ 49 a[++V]=s[i]-‘0‘; 50 st_num.push(V); 51 if ((!st_op.empty())&&(st_op.top()!=-1))merge(); 52 } 53 else{ 54 if (s[i]==‘(‘)st_op.push(-1); 55 if (s[i]==‘<‘)st_op.push(0); 56 if (s[i]==‘>‘)st_op.push(1); 57 if (s[i]==‘?‘){ 58 st_op.push(2); 59 flag=1; 60 } 61 if (s[i]==‘)‘){ 62 st_op.pop(); 63 if ((!st_op.empty())&&(st_op.top()!=-1))merge(); 64 } 65 } 66 while (!st_op.empty())merge(); 67 for(int i=0;i<(1<<m);i++)dfs(V,i); 68 for(int i=1;i<=n;i++){ 69 for(int j=0;j<m;j++)id[j]=j; 70 p=i; 71 sort(id,id+m,cmp); 72 id[m]=m; 73 int s=0; 74 for(int j=0;j<m;j++){ 75 s|=(1<<id[j]); 76 ans=(ans+1LL*f[s][V][1]*(b[id[j]][i]-b[id[j+1]][i]))%mod; 77 } 78 } 79 printf("%d",ans); 80 return 0; 81 }
标签:merge int code 树形dp blog i++ 接下来 spl char
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14382818.html