参考资料:
[1]:官方题解(提取码:t050 )
[2]:标程(提取码:rvxr )
[3]:牛客题解汇总
A.Equivalent Prefixes(单调栈)
•题意
定义两个数组 u,v ,并且 u,v 都含有 m 个互不相同的元素;
如果数组 u,v 任意区间的RMQ(区间最小值)对应的下标都相等,则说这两个数组是 "equivalent";
先给你包含 n 个不同元素的数组 a,b,求使得 a[1,2,...,p] 与 b[1,2,....,p] 为 "equivalen" 的最大的 p;
•题解
定义数组 L1,L1[ i ]表示在 a 数组中,以 ai 为区间最小值最左可以到达的位置;
即 RMQ( L1[ i ], i ) = ai;
定义数组 L2,含义与 L1 相同,作用于数组 b;
对于位置 i ,找到第一个不满足 L1[i] == L2[ i ] 的位置 i,那么,答案就为 i-1;
•Code
View Code1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 using namespace std; 5 #define ll long long 6 const int maxn=1e5+50; 7 8 int n; 9 int a[maxn]; 10 int b[maxn]; 11 int L1[maxn]; 12 int L2[maxn]; 13 stack<int >sta; 14 15 void Work(int *a,int *L) 16 { 17 while(!sta.empty()) 18 sta.pop(); 19 for(int i=1;i <= n;++i) 20 { 21 while(!sta.empty() && a[sta.top()] >= a[i]) 22 sta.pop(); 23 24 L[i]=sta.empty() ? 1:sta.top()+1; 25 sta.push(i); 26 } 27 } 28 int Solve() 29 { 30 Work(a,L1); 31 Work(b,L2); 32 33 int p=n; 34 for(int i=1;i <= n;++i) 35 if(L1[i] != L2[i]) 36 { 37 p=i-1; 38 break; 39 } 40 return p; 41 } 42 int main() 43 { 44 while(~scanf("%d",&n)) 45 { 46 for(int i=1;i <= n;++i) 47 scanf("%d",a+i); 48 for(int i=1;i <= n;++i) 49 scanf("%d",b+i); 50 51 printf("%d\n",Solve()); 52 } 53 return 0; 54 }
E.ABBA(DP or 组合数学)
•参考资料
[1]:唐宋元明清(DP)
[2]:光芒万丈小太阳(DP)
[3]:rjmgc丁凯朔(组合数学)(待参考)
•题意
求包含 n 个 "AB" 和 m 个 "BA" 的总方案数;
•题解
比赛结束当天,查看了参考资料[2]的博文,当时出于似懂非懂的状态;
今天(2019.7.21)重新看了一下这道题,又看了另一篇博文参考资料[1];
有种恍然大悟的感觉,但任然欠缺点东西,先记录以下,万一那天顿悟了呢。
定义 dp[ i ][ j ] 表示当前包含 i 个 'A' 和 j 个 'B' 的合法序列的总方案数;
如果 i+1 ≤ n+j,转移 : dp[i+1][ j ] += dp[ i ][ j ];
如果 j+1 ≤ m+i,转移 : dp[ i ][ j+1] += dp[ i ][ j ];
这两篇博客对比着理解以下,应该更容易些;(tql)
•Code
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int MOD=1e9+7; 5 const int maxn=4e3+50; 6 7 int n,m; 8 ll dp[maxn][maxn]; 9 10 ll Solve() 11 { 12 int s=n+m; 13 for(int i=0;i <= s;++i) 14 for(int j=0;j <= s;++j) 15 dp[i][j]=0; 16 dp[0][0]=1; 17 18 for(int i=0;i <= s;++i) 19 { 20 for(int j=0;j <= s;++j) 21 { 22 if(i+1 <= n+j) 23 dp[i+1][j]=(dp[i+1][j]+dp[i][j])%MOD; 24 if(j+1 <= m+i) 25 dp[i][j+1]=(dp[i][j+1]+dp[i][j])%MOD; 26 } 27 } 28 return dp[s][s]; 29 } 30 int main() 31 { 32 while(~scanf("%d%d",&n,&m)) 33 { 34 printf("%d\n",Solve()); 35 } 36 return 0; 37 }