求线段树解法
查看原帖
求线段树解法
356117
落木之樱meow楼主2024/8/3 18:46

求线段树解法

因为这个和扫描线板子很像所以赛时尝试用线段树写,但是比赛中爆零,没想明白怎么写pushup()

感谢各位神仙,悬赏关注

赛时代码WA

#include <stdio.h>
#include <algorithm>
#define N 1000000
#define lc (cur * 2)
#define rc (cur * 2 + 1)
typedef long long ll;
inline ll max(ll x, ll y) {return (x > y) ? x : y;}

struct node{
    int l, r;
    int cnt;
    ll sum;

    int cntl, cntr;
} tree[N*4];

int n, m;
ll f[N];
ll fn[N];

int lenTemp;
ll temp[N*4];

inline void pushup(int cur) {
    if (tree[cur].cnt > 0) {
        tree[cur].cntl = tree[cur].cntr = tree[cur].cnt;
        if (tree[cur].cnt == 1) {
            tree[cur].sum = temp[tree[cur].r] - temp[tree[cur].l] + 1;
        } else {
            tree[cur].sum = 0;
        }
    } else if (tree[cur].l == tree[cur].r) {
        tree[cur].sum = 0;
        tree[cur].cntl = tree[cur].cntr = tree[cur].cnt;
    } else {
        tree[cur].sum = tree[lc].sum + tree[rc].sum;
        if (tree[lc].cntr == 1 && tree[rc].cntl == 1) tree[cur].sum += temp[tree[rc].l] - temp[tree[lc].r] - 1;
        tree[cur].cntl = tree[lc].cntl, tree[cur].cntr = tree[rc].cntr;
    }
}

void init(int cur, int l, int r) {
    tree[cur].l = l, tree[cur].r = r;
    if (l == r) {
        tree[cur].cnt = tree[cur].sum = 0;
        return;
    }
    int mid = (l+r)/2;
    init(lc, l, mid);
    init(rc, mid + 1, r);
    pushup(cur);
}

void work(int cur, int sta) {
    tree[cur].cnt += sta;
    pushup(cur);
}

void update(int cur, int l, int r, int sta) {
    if (tree[cur].l >= l && tree[cur].r <= r) {
        work(cur, sta);
        return;
    }
    int mid = (tree[cur].l + tree[cur].r) / 2;
    if (l <= mid) update(lc, l, r, sta);
    if (r >= mid + 1) update(rc, l, r, sta);
    pushup(cur);
}

void outTree();

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &f[i]);
        fn[i] = f[i] + m - 1;
        temp[++lenTemp] = f[i];
        temp[++lenTemp] = fn[i];
        temp[++lenTemp] = f[i] - 1;
        temp[++lenTemp] = fn[i] + 1;
    }
    std::sort(temp+1, temp+1+lenTemp);
    lenTemp = std::unique(temp+1, temp+1+lenTemp) - temp - 1;
    
    
    for (int i = 1; i <= n; i++) {
        f[i] = std::lower_bound(temp+1, temp+1+lenTemp, f[i]) - temp;
        fn[i] = std::lower_bound(temp+1, temp+1+lenTemp, fn[i]) - temp;
    }
    init(1, 1, lenTemp);
    for (int i = 1; i <= n; i++) {
        update(1, f[i], fn[i], 1);    
        printf("len: %d, i=%d\n", lenTemp, i);
        for (int i = 1; i <= lenTemp; i++) {
            printf("%d ", i);
        }
        printf("\n");
        for (int i = 1; i <= lenTemp; i++) {
            printf("%d ", temp[i]);
        }
        printf("\n");
        printf("[%d, %d]\n", f[i], fn[i]);
        outTree();
    }
    // printf("%d\n", tree[1].sum);
    ll res = 0;
    for (int i = 1; i <= n; i++) {
        update(1, f[i], fn[i], -1);
        res = max(res, tree[1].sum + m);
        update(1, f[i], fn[i], 1);
    }
    printf("%lld", res);
    return 0;
}

void outTree() {
    for (int i = 1; i <= 33; i++) {
        printf("%d: [%d, %d], cnt=%d, sum=%d, cntl=%d, cntr=%d\n", i, tree[i].l, tree[i].r, tree[i].cnt, tree[i].sum, tree[i].cntl, tree[i].cntr);
    }
    printf("\n");
}
2024/8/3 18:46
加载中...