2020 牛客暑期多校 第二场 G-Greater and Greater(bitset)

题目传送门

题意: 给你一个长度为n的数组a,一个长度为m的数组b,问你A中有多少个子数组S,满足S[i]>=b[i],i∈{1,2,3,…m}。

思路: 开两个bitset,ans表示数组a中的哪些位置可能可以作为开头,temp表示原数组a中哪些位置可以匹配到当前的b[i]。我们先对a和b数组记录位置并分别排序,这样temp就可以一直沿用,因为排序之后大于b[i].first的肯定大于b[i+1].first。每次更新完temp之后,大于b[i].first的就找出来了。找到之后,比如原数组中第k个元素可以匹配当前b[i].fi,temp中第k位是等于1的,我们将temp右移(b[i].second-1)位,就表示原数组a中第(k-b[i].se-1)可能作为开头,把排序后的b数组遍历完成之后,就得到了最后的ans,这时候ans中的1就是完全合法的了。输出1的个数就行。

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
//#define int long long
#define pii pair<int,int>
#define pdd pair<double,double>
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=2e5+5;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-7;
const double PI=acos(-1);
pii a[N],b[N];
bitset<N>ans,temp;
bool cmp(pii a,pii b)
{
    return a.fi>b.fi;
}
signed main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].fi;
        a[i].se=i;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>b[i].fi;
        b[i].se=i;
    }
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+m+1,cmp);
    ans.set();
    temp.reset();
    for(int i=1,j=1;i<=m;i++)
    {
        while(j<=n&&a[j].fi>=b[i].fi)
            temp.set(a[j++].se);
        ans&=(temp>>(b[i].se-1));
    }
    cout<<ans.count()<<endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值