2020牛客暑期多校训练营(第二场)G Greater and Greater 题解

题意:

给一个长为n的序列A,一个长为m的序列B,要求计算有多少个i(1<=i<=n-m+1),使得A[i+j-1]>=B[j](1<=j<=m)

当时第一反应是魔改KMP,用next数组求答案,然后各种魔改各种WA,遂放弃。

我们考虑利用bitset求解。

我们先求出长为m的bitset F[i],F[i][j]表示A[i]是否大于等于B[j],显然,本质不同的F[i]只有m种。

所以求我们不必直接求F数组,而是先求出本质不同的那m种情况的bitset,需要用F[i]时直接二分就可以了。

可以发现,如果 i 满足A[i+j-1]>=B[j](1<=j<=m),则F[i][1]=1,F[i+1][2]=1,F[i+2][3]=1……

因此,我们设长度为m的滚动bitset ans,每次ans右移一位,与上A[i],此时ans[0]为F[i][1]&F[i+1][2]&F[i+2][3]……,若ans[0]为1则说明i可行。

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<bitset>
 8 #define N 150005
 9 #define M 50005
10 using namespace std;
11 int n,m,A[N],B[N];
12 struct no{
13     int val,id;
14 }node[N];
15 bool cmp(no a,no b)
16 {
17     if(a.val==b.val)return a.id<b.id;
18     return a.val<b.val;
19 }
20 bitset<M> S[M],ans;
21 int find(int x)
22 {
23     if(x<node[1].val)return 0;
24     if(x>node[m].val)return m;
25     int li=1,ri=m,mid,ans=-1;
26     while(li<=ri)
27     {
28         mid=(li+ri)>>1;
29         if(node[mid].val<=x) li=mid+1,ans=mid;
30         else ri=mid-1;
31     }
32     return ans;
33 }
34 int main()
35 {
36     scanf("%d%d",&n,&m);
37     for(int i=1;i<=n;i++)
38     {
39         scanf("%d",&A[i]);
40     }
41     for(int i=1;i<=m;i++)
42     {
43         scanf("%d",&B[i]);
44         node[i].val=B[i];
45         node[i].id=i;
46     }
47     sort(node+1,node+m+1,cmp);
48     for(int i=1;i<=m;i++)
49     {
50         S[i]=S[i-1];
51         S[i].set(node[i].id-1);
52     }
53     for(int i=n;i>n-m+1;i--)
54     {
55         int op=find(A[i]);
56         ans>>=1;
57         ans.set(m-1);
58         ans&=S[op];
59     }
60     int sum=0;
61 //    cout<<endl;
62     for(int i=n-m+1;i;i--)
63     {
64         int op=find(A[i]);
65     //    cout<<i<<endl;
66         
67         ans>>=1;
68     //    for(int j=0;j<m;j++) cout<<ans[j]<<' ';
69     //    cout<<endl;
70         ans.set(m-1);
71         ans&=S[op];
72     //    cout<<i<<endl;
73         sum+=ans[0];
74     }
75     printf("%d\n",sum);
76     return 0;
77 }
View Code

 

posted @ 2020-07-14 11:25  Hzoi_joker  阅读(385)  评论(0编辑  收藏  举报