CF338E Optimize!

https://www.luogu.com.cn/problem/CF338E

转换一手

b [ i ] = h − b [ i ] b[i]=h-b[i] b[i]=hb[i],那么条件完美匹配条件变为排序后 a [ i ] > b [ i ] a[i]>b[i] a[i]>b[i],容易证明这是充要的

转换到这一步还是不太好做

考虑离散化后把 b [ i ] b[i] b[i]设为 − 1 -1 1 a [ i ] a[i] a[i]设为 1 1 1,
维护权值的前缀和,那么就要保证每个前缀和都 > = 0 >=0 >=0,这个可以用线段树轻松实现
代码实现很简单

code:

#include<bits/stdc++.h>
#define N 300050
#define ls (rt << 1)
#define rs (rt << 1 | 1)
using namespace std;
int mi[N << 2], tg[N << 2];
void padd(int rt, int o) {
    mi[rt] += o, tg[rt] += o;
}
void pushdown(int rt) {
    if(tg[rt]) {
        padd(ls, tg[rt]), padd(rs, tg[rt]);
        tg[rt] = 0;
    }
}
void update(int rt) {
    mi[rt] = min(mi[ls], mi[rs]);
}
void add(int rt, int l, int r, int L, int R, int o) {
    if(L <= l && r <= R) {padd(rt, o); return ;}
    pushdown(rt);
    int mid = (l + r) >> 1;
    if(L <= mid) add(ls, l, mid, L, R, o);
    if(R > mid) add(rs, mid + 1, r, L, R, o);
    update(rt);
}
int n, m, H, lim, a[N], b[N], lss[N << 1];
int main() {
    scanf("%d%d%d", &n, &m, &H);
    for(int i = 1; i <= m; i ++) scanf("%d", &b[i]), b[i] = H - b[i], lss[++ lim] = b[i];
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), lss[++ lim] = a[i];
    sort(lss + 1, lss + 1 + lim);
    lim = unique(lss + 1, lss + 1 + lim) - lss - 1;
    for(int i = 1; i <= m; i ++) b[i] = lower_bound(lss + 1, lss + 1 + lim, b[i]) - lss;
    for(int i = 1; i <= n; i ++) a[i] = lower_bound(lss + 1, lss + 1 + lim, a[i]) - lss;
    
    for(int i = 1; i <= m; i ++) add(1, 1, lim, a[i], lim, -1), add(1, 1, lim, b[i], lim, 1);
    int ans = 0;
    ans += mi[1] >= 0;
    for(int i = m + 1; i <= n; i ++) add(1, 1, lim, a[i - m], lim, 1), add(1, 1, lim, a[i], lim, -1), ans += mi[1] >= 0;
    printf("%d", ans);
    return 0;
}
posted @ 2021-10-11 07:45  lahlah  阅读(85)  评论(0编辑  收藏  举报