2020牛客多校第二场(G题)Greater and Greater

题目描述:给定大小为n的序列A和大小为m的序列B,计算A中所有大小为m的子区间S,满足
S i > = B i 1 < = i < = m S_{i} >= B_{i} {1 <= i <= m } Si>=Bi1<=i<=m

f 是 a 中哪些位置的数大于等于当前数。如果大于 置为1,
ans 就是哪些位置满足条件, ans[i] 代表区间 [i, i + m], 是不是满足条件。

用 bitset 搞一下,
直接暴力肯定是不行的,
然后我们考虑到每一个 b[i], 它会影响哪些 s[i], s[i] 代表 a[i] - a[i+m],
只有 a 中的大于等于 b[i] 的数, 这些数对应的 s[i] 才能为1, 否则为0, 为0就代表s[i] 不满足条件。

所以我们对 a 和 b 从大到小排序, 带着下标一起,
枚举 b 的值x, 把 a 中大于等于 x 的值的下标在 f 中标记一下, 在枚举下一个值的时候,之前的值肯定大于当前的值,因为是从大到小排序的。
当前的枚举的 i , 他在b数组中的位置就是 b[i].pos, 那么它就会影响 ans[1] - ans[ n - b[i].pos] 的值。
公式就是: ans &= f >> b[i].pos

思考:

对于这样的题, 整体上不太会,
那么就要考虑个体对于整体的影响,
考虑每一个个体,它和整体是什么关系。

#include
using namespace std;
const int N = 2e5+100;
bitset<N>ans,f;
void dbg() {cout << endl;}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}
struct node{
    int pos, x;
    bool operator < (const node &A) const {
        return x > A.x;
    }
}a[N],b[N];
int n,m;
int main(){
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= n; ++i)
        scanf("%d",&a[i].x), a[i].pos = i;
    for (int i = 1; i <= m; ++i)
        scanf("%d",&b[i].x), b[i].pos = i;
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    ans.set(); f.reset();

    for (int i = 1, j = 0; i <= m; ++i){
        while((j+1) <= n && a[j+1].x >= b[i].x){
            f[a[j+1].pos] = 1;
            j++;
        }
        ans &= (f >> b[i].pos);
    }
    printf("%d\n",(int)ans.count());
    return 0;
}

你可能感兴趣的:(多校,bitset)