牛客第十场 F.Popping Balloons

第一维直接遍历 第二维用线段树维护每个最左端可以得到的贡献

在线段树上每次删除一个点会影响到 X   X-R   X-2*R  3个值 最多操作1e5次 复杂度 6*n*logn(删了还要加回来

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 300005;
int num[MAXN];
int number[MAXN];
struct Seg_Tre {
        int l, r;
        int w;
} tree[MAXN << 2];
inline void push_up(int x) {
        tree[x].w = max(tree[x << 1].w, tree[(x << 1) | 1].w);
}
inline void build(int x, int ll, int rr) {
        tree[x].l = ll, tree[x].r = rr;
        if (tree[x].l == tree[x].r) {
                tree[x].w = number[ll];
                return;
        }
        int m = (ll + rr) >> 1;
        build(x << 1, ll, m);
        build((x << 1 | 1), m + 1, rr);
        push_up(x);
}
inline void change_point(int x, int aim, int add) {
        if (tree[x].l == tree[x].r) {
                tree[x].w += add;
                return;
        }
        int m = (tree[x].l + tree[x].r) >> 1;
        if (aim <= m) {
                change_point(x << 1, aim, add);
        } else {
                change_point((x << 1) | 1, aim, add);
        }
        push_up(x);
}
inline int ask_interval(int x, int ll, int rr) {
        if (tree[x].l > rr || tree[x].r < ll)
                return -1;
        if (tree[x].l >= ll && tree[x].r <= rr) {
                return tree[x].w;
        }
        int now = 0;
        int m = (tree[x].l + tree[x].r) >> 1;
        if (ll <= m) {
                now = max(now, ask_interval(x << 1, ll, m));
        }
        if (rr > m) {
                now = max(now, ask_interval((x << 1) | 1, m + 1, rr));
        }
        return now;
}
vector<int> G[MAXN];
int main() {
 
        int n, r;
        int x, y;
        scanf("%d %d", &n, &r);
        for (int i = 1; i <= n; i++) {
                scanf("%d %d", &x, &y);
                G[x].push_back(y);
                num[y]++;
        }
        for (int i = 0; i <= 100000; i++) {
                for (int j = 0; j <= 2; j++) {
                        if (i + j * r <= 100000) {
                                number[i] += num[i + j * r];
                        }
                }
        }
        build(1, 0, 100000);
        int ansnow = 0;
        for (int i = 0; i <= 100000; i++) {
                int now = 0;
                for (int j = 0; j <= 2; j++) {
                        int u = i + j * r;
                        if (u > 100000)
                                break;
                        for (int v : G[u]) {
                                now++;
                                for (int k = 0; k <= 2; k++)
                                        if (v - k * r >= 0)
                                                change_point(1, v - k * r, -1);
                        }
                }
                ansnow = max(ansnow, now + ask_interval(1,0,100000));
                for (int j = 0; j <= 2; j++) {
                        int u = i + j * r;
                        if (u > 100000)
                                break;
                        for (int v : G[u]) {
                                now++;
                                for (int k = 0; k <= 2; k++)
                                        if (v - k * r >= 0)
                                                change_point(1, v - k * r, 1);
                        }
                }
        }
        printf("%d\n", ansnow);
        return 0;
}
View Code

 

posted @ 2019-08-18 01:03  Aragaki  阅读(186)  评论(0编辑  收藏  举报