牛客多校第一场
?
A
題意:給兩個相同長度的數(shù)字串,求一個最大的p,使兩個數(shù)字串都滿足[1,p]中任何一個區(qū)間的最小值下標(biāo)都相同,
思路:對于兩個數(shù)字串要求最大的p,可以想到這個p的左邊的區(qū)間[1,x]也肯定滿足,所以想到從左往右順推,然后每次都新加一個數(shù)字,判斷這個新的區(qū)間是否滿足,就只需要判斷這個數(shù)字左側(cè)第一個比它小的數(shù)字位置是否相同,如果相同那么新加的這個數(shù)字可以,否則最長長度到此為止。判斷每個數(shù)字左側(cè)第一個比它小的位置可以用單調(diào)棧維護(hù)一個遞增的序列來求,對于每次入棧的數(shù)字,棧中上一個元素的位置就是第一個比它小的位置。
#include<bits/stdc++.h> using namespace std;const int maxn=1e5+10; int a[maxn],b[maxn]; int st[maxn]; int lmin1[maxn],lmin2[maxn];int main() {int n;while(~scanf("%d",&n)){for(int i=1; i<=n; i++)scanf("%d",&a[i]);for(int i=1; i<=n; i++)scanf("%d",&b[i]);int l,r;l=1;r=0;for(int i=1; i<=n; i++){while(l<=r&&a[st[r]]>=a[i])r--;lmin1[i]=st[r];st[++r]=i;}l=1;r=0;for(int i=1; i<=n; i++){while(l<=r&&b[st[r]]>=b[i])r--;lmin2[i]=st[r];st[++r]=i;}int ans=0;for(int i=1; i<=n; i++){if(lmin1[i]==lmin2[i])ans=i;elsebreak;}printf("%d\n",ans);} }View Code
?
E
題意:求有多少種字符串滿足含有n個AB的子序列和m個BA的子序列。
思路:咋這么難想了QAQ,設(shè)狀態(tài)轉(zhuǎn)移方程f[i,j]表示:(在構(gòu)成這個長度為n+m的字符串的過程中)前綴長度為i+j的字符串中有i個A和j個B的合法方案數(shù)有多少,合法方案就是可能滿足條件的方案,可以想到不滿足條件的方案就是前i+j中出現(xiàn)了大于n+j(j<=m)個A或者前i+j中出現(xiàn)了大于m+i(i<=n)個B,其余的都是合法方案,然后轉(zhuǎn)移方程f[i][j]+=f[i-1][j]&&f[i][j]+=f[i][j-1]表示只能從前一個長度的字符串加個A或者加個B的方案數(shù)轉(zhuǎn)移過來。
#include<bits/stdc++.h> using namespace std;const int maxn=1e3+10; const int mod=1e9+7; #define ll long long ll f[maxn*2][maxn*2]; int main() {int n,m;while(~scanf("%d%d",&n,&m)){for(int i=0; i<=n; i++)f[i][0]=1;for(int i=0; i<=m; i++)f[0][i]=1;for(int i=1; i<=n+m; i++)for(int j=1; j<=n+m; j++){if(i<=(n+min(j,m))) f[i][j]=(f[i][j]+f[i-1][j])%mod;if(j<=(m+min(i,n))) f[i][j]=(f[i][j]+f[i][j-1])%mod;}printf("%lld\n",f[n+m][n+m]);} }View Code
?
轉(zhuǎn)載于:https://www.cnblogs.com/dongdong25800/p/11219092.html
總結(jié)
- 上一篇: loj2058 「TJOI / HEOI
- 下一篇: TPS与QPS