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

题目链接

题面:
在这里插入图片描述
题意:
问A序列有多少个连续子序列,满足所有的 Ai>=Bi

官方题解:
在这里插入图片描述

①、按照我理解的题解写。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x)  (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=200100;
const int maxm=100100;
const int up=100000;

bitset<40001>bi[40001],now;
struct node
{
    int val;
    int id;
}a[maxn],b[maxn];
int c[maxn];

bool cmp(const node &a,const node &b)
{
    return a.val<b.val;
}

int main(void)
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].val);
        a[i].id=i;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&b[i].val);
        b[i].id=i;

    }
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+m+1,cmp);
    //预处理比i位置的a小的b有哪些位置
    //这些状态一共只有m种。
    int cm=1;
    for(int i=1;i<=m;i++)
    {
        bi[i]=bi[i-1];
        bi[i].set(b[i].id);
        while(cm<=n&&a[cm].val<b[i].val)
            c[a[cm].id]=i-1,cm++;
    }
    while(cm<=n) c[a[cm].id]=m,cm++;
    int ans=0;
    //b[c[i]]表示对于i位置的a来说,有哪些位置的b小于a
    for(int i=1;i<=n;i++)
    {
        now<<=1;
        now.set(1);
        //now为1的位表示当前哪些位置的b应该小于a
        //b[c[i]]表示对于i位置的a来说,有哪些位置的b小于a
        //两者按位&,就是当前可到达的状态
        now=now&bi[c[i]];
        if(now[m]==1) ans++;
    }
    cout<<ans<<endl;
    return 0;
}


②、学习马哥的代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x)  (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=200100;
const int maxm=100100;
const int up=100000;

bitset<maxn>res,vis;
struct node
{
    int val;
    int id;
}a[maxn],b[maxn];
int c[maxn];

bool cmp(const node &a,const node &b)
{
    return a.val<b.val;
}

int main(void)
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].val);
        a[i].id=i;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&b[i].val);
        b[i].id=i;

    }
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+m+1,cmp);

    int cm=1;
    //vis为1的地方表示,对于当前的bi,a序列中有哪些地方比b[i].val小
    //如果某个地方pos比当前的b[i].val小,那么pos-b[i].id+1的位置就不可能形成一个符合要求的序列
    //因为如果能形成一个序列,那么哪个序列的第pos-b[i].id+1的位置,也就是pos位置小于b[i].id,这是不符合要求的
    //所以我们找出所有的这些开头。
    //就是vis中那些为1的地方右移(b[i].id-1)位。
    //bitset是按照正常的二进制顺序 高位10000001111低位
    for(int i=1;i<=m;i++)
    {
        while(cm<=n&&a[cm].val<b[i].val)
            vis.set(a[cm++].id);
        res|=(vis>>(b[i].id-1));
    }
    int ans=0;
    for(int i=1;i<=n-m+1;i++)
        if(res[i]==0) ans++;
    cout<<ans<<endl;
    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值