• 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
    ",sum);
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    Linux网络编程--socket
    UDP学习总结
    TCP协议学习总结
    DNS协议总结
    DHCP协议总结
    ARP协议总结
    二层协议--MPLS协议总结
    二层协议--LLDP协议总结
    二层协议--LACP协议总结
    二层协议--STP协议总结
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13298081.html
Copyright © 2020-2023  润新知