【2020牛客多校第二场】G题 Greater and Greater
G题 Greater and Greater
题面
题目描述:给定大小为n的序列A和大小为m的序列B,计算A中所有大小为m的子区间S,满足
$ \forall i \in {1,2,...m}, S_i \leq B_i $
思路
因为A序列中每个数字只有两种状态(比\(b_i\)大或小)所以很容易想到二进制处理
先不考虑复杂度
\(对每个B_i遍历A数组,判定大小,然后就有了m个01序列\)
对于样例是这样的(从左到右,下标从1开始)
\(B_1=2 \quad 011111\)
\(B_2=3 \quad 010111\)
\(B_3=3 \quad 010111\)
这样就求出了所有点可以站的 '位置' 只需要找到一个 '楼梯' 全是1能走下来就行了,忽略这句自己yy的话
根据上面的思想,每次只用把01序列移动i-1位,最后看一下有多少位同时为1就行了(&)
\[B_1=011111\quad移动0位\\
B_2=10111\quad 移动1位\\
B_3=0111\quad 移动2位\\
temp=B_1 \&B_2\&B_3\\
ans=temp.cout()
\]
\(对A,B序列排序,来使数字总是递增的保证复杂度\)
初始化全为1,因为是递增,所以\(A_{posx}>=B_i就一定有A_{posx+1}>=B_i\)
我当时怎么就没想到排序两个数组(我居然是排序一个数组然后想二分😂,拆点bfs)是说复杂度总是不对
二进制操作bitset更方便 没用过几次
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5, M = 4e3 + 5;
int n, m;
struct node
{
int num,pos;
}a[N],b[N];
bool cmp(node x,node y)
{
return x.num < y.num;
}
bitset<N> bi,ans;
int main()
{
scanf("%d %d", &n,&m);
for (int i = 1; i <= n;i++)
{
scanf("%d", &a[i].num);
a[i].pos = i;
}
for (int i = 1; i <= m;i++)
{
scanf("%d", &b[i].num);
b[i].pos = i;
}
sort(a + 1, a + n + 1, cmp);
sort(b + 1, b + m + 1, cmp);
ans.set();//全为1
bi.set();//全为1
int posx = 1;
for (int i = 1; i <= m;i++)
{
while(posx<=n&&a[posx].num<b[i].num)
{
bi.reset(a[posx].pos);//不满足,变0
posx++;
}
//cout << (bi>>(b[i].pos-1)) << endl;
ans = ans & (bi >> (b[i].pos-1));
}
int tot = 0;
for (int i = 1; i <= n-m+1;i++)
{
if(ans[i]&1)
tot++;
}
printf("%d\n", tot);
return 0;
}
/*
*/
话说牛客re也算wa的吗...
$道路千万条,点赞第一条;阅读不规范,笔者两行泪$