【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的吗...

posted @ 2020-07-16 21:36  Sakura_Momoko  阅读(186)  评论(2编辑  收藏  举报