[2019牛客]第一场

题目链接

A:Equivalent Prefixes

给你两个长度为n的序列a、b,求一个最大k值使,i-k 中任意一个区间的最小值下标都相同

 

我们用单调栈处理每个元素作为最小值的左端点。

我们把下标放进栈中,比较的时候比较具体的值,维护一个值逐渐变大的单调栈。

若当前栈为空,则说明没有比当前值更小的元素,那么就从1开始。

其他就为 比当前值更小的元素下标+1

最后比较两个元素的左端点值是否相同就可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <stack>
 9 #include <vector>
10 #include <cctype>
11 #include <sstream>
12 using namespace std;
13 typedef long long ll;
14 const int inf=0x7fffffff;
15 const int N=100000+100;
16 const int M=5000+10;
17 const double PI=acos(-1.0);
18 int T,n;
19 int a[N],b[N];
20 int A[N],B[N];
21 void solve(int t[],int a[])
22 {
23     stack<int>s;
24     for(int i=1;i<=n;i++)
25     {
26         while(s.size()&&a[s.top()]>a[i])
27             s.pop();
28         if(s.empty())   t[i]=1;
29         else    t[i]=s.top()+1;
30         s.push(i);
31     }
32 }
33 int main()
34 {
35         while(scanf("%d",&n)!=EOF)
36         {
37 
38         int ans=n+1;
39         for(int i=1;i<=n;i++)
40             scanf("%d",&a[i]);
41         for(int i=1;i<=n;i++)
42             scanf("%d",&b[i]);
43         solve(A,a);
44         solve(B,b);
45         for(int i=1;i<=n;i++)
46             if(A[i]!=B[i])
47             {
48                 ans=i;  break;
49             }
50         printf("%d\n",ans-1);
51         }
52 
53 
54 
55     return 0;
56 }
View Code

 

当时暴力了一种写法也过了。

每加入一个元素,判断加入这个元素对原本序列的影响。

也就是说加入一个元素下标为i,有影响的是 前面的询问 [i-1,i]  [i-2,i] [i-3,i].....

若 同一下标 a[x]和b[x]都大于当前元素 continue;

若 同一下标 a[x]和b[x]都小于当前元素 break;跳出这个循环,不用往前面看,前面的序列一定都满足条件

若 同一下标 a[x]和b[x] 一个大于当前元素,另一个小于当前元素 这个就不成立了。

这种情况在最坏的情况下是 O(n*n)

 

 

E:ABBA

题目当时没看懂,以为就是有n个ab和m个ba

应该要知道 什么都没有的情况为1的。 f[0][0]=1;

题目是说有一个长度为 2(n+m) 的字符串,其中有(n+m)个A,(n+m)个B

其中有n个AB字串,m个BA字串。我们要知道这个字串的定义是不一定连续的。

也就是说 前n个‘A’一定是AB的‘A’,前m个'B'一定是BA的‘B’

主要是dp还不太会,一会去补dp专题。

设f[i][j]为有 i个'A',j个‘B’ 的字串数量。

当 i<n 时 f[i+1][j]+=f[i][j] 我们可以往后放一个‘A’

当min(j,m)> i-n 也就是说 当前放的B的数量要大于 ‘A’多的数量  我们也可以往后面放一个‘A’

B同理可得:

 1 for(int i=0;i<=n+m;i++)
 2             for(int j=0;j<=n+m;j++)
 3         {
 4             if(i<n||min(j,m)>i-n)
 5             {
 6                 f[i+1][j]+=f[i][j];
 7                 f[i+1][j]%=mod;
 8             }
 9             if(j<m||min(i,n)>j-m)
10             {
11                 f[i][j+1]+=f[i][j];
12                 f[i][j+1]%=mod;
13             }
14         }
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <stack>
 9 #include <vector>
10 #include <cctype>
11 #include <sstream>
12 using namespace std;
13 typedef long long ll;
14 const int inf=0x7fffffff;
15 const int N=100000+100;
16 const int M=5000+10;
17 const int mod=1e9+7;
18 const double PI=acos(-1.0);
19 int n,m;
20 int f[2100][2100];
21 int main()
22 {
23     while(scanf("%d %d",&n,&m)!=EOF)
24     {
25         for(int i=0;i<=n+m;i++)
26             for(int j=0;j<=n+m;j++)
27                 f[i][j]=0;
28         f[0][0]=1;
29         for(int i=0;i<=n+m;i++)
30             for(int j=0;j<=n+m;j++)
31         {
32             if(i<n||min(j,m)>i-n)
33             {
34                 f[i+1][j]+=f[i][j];
35                 f[i+1][j]%=mod;
36             }
37             if(j<m||min(i,n)>j-m)
38             {
39                 f[i][j+1]+=f[i][j];
40                 f[i][j+1]%=mod;
41             }
42         }
43         printf("%d\n",f[n+m][n+m]);
44     }
45 
46 
47 
48     return 0;
49 }
View Code

 

转载于:https://www.cnblogs.com/Kaike/p/11249904.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值