题面:
题意:
问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;
}