Happy Triangle

Happy Triangle

题意:

给一个多重集和,你要q次操作

  1. 向多重集合里插入一个x。
  2. 向多重集合里删一个x(数据保证删除的数存在再集合中国)。
  3. 给你一个x,问能否再 多重集合中选两个数判断是否可以构成三角形。

题解:

构造三角形 必须要 \(a + b >x ,and, a - b < x\) 这个两个条件必须同时满足。

想要第一个条件满足(a + b > x)

如果 \(a \ge \frac{x}{2} + 1\) 那么 只要 \(b \ge a\) 则一定满足第一个条件。

要是 \(b < a\) 呢?

很显然也是有可能满足第一个条件。

因为我们还需要满足第二个条件 (a - b < x) 那 b < a中所有满足第一个条件的是不是只要贪心找第一个小于 a的就行了,因为这样的 a - b 一定是最小。

假设我们找到的位置是 pos (即pos 到 无穷大随便选两个都满足第一个条件)

然后就是找第二个条件, 用线段树维护前一个与后一个的差值, 维护最小值就行了。

要是最小值 都大于x 那么, 一定是不可行的。

细节比较多!!!

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
  
int a[N], q, top = 1, rt, maxn;
  
struct segement {
    int l, r, sum;
}tree[30 * N];
  
#define m (l + r) / 2
  
map<int, int> g;
  
  
void update(int val, int &now, int pos, int l, int r) {
    if (!now) now = top++;
    if (l == r) {
  
        tree[now].sum = val;
        return;
    }
    if (pos <= m) update(val, tree[now].l, pos, l, m);
    else update(val, tree[now].r, pos, m + 1, r);
  
    tree[now].sum = min(tree[tree[now].l].sum, tree[tree[now].r].sum);
  
}
  
int query(int now, int ql, int qr, int l, int r) {
    if (l > r) return 2e9;
    if (ql <= l && qr >= r) {
        return tree[now].sum;
    }
    int ans = INT_MAX;
    if (ql <= m) ans = min(ans, query(tree[now].l, ql, qr, l, m));
    if (qr > m) ans = min(ans, query(tree[now].r, ql, qr, m + 1, r));
    return ans;
}
  
  
void add(int x) {
    g[x]++;
    auto it = g.lower_bound(x);
    if (it -> second > 1) {
        update(0, rt, x, 1, maxn);
    } else {
        if (it != g.begin()) {
            it--;
            update(x - (it -> first), rt, x, 1, maxn);
            it++;
        }
        if (it != g.end()) {
            it++;
            if (it != g.end() && it -> second == 1) {
                update((it -> first) - x, rt, (it -> first), 1, maxn);
            }
        }
    }
  
}
  
void deleate(int x) {
    g[x]--;
 
    if (g[x] == 0) {
        auto it = g.lower_bound(x);
        g.erase(it);
        it = g.lower_bound(x);
        update(2e9, rt, x, 1, maxn);
        if (it != g.begin() && it != g.end() && it -> second == 1) {
            int cat = it -> first;
            it--;
            update(cat - (it -> first), rt, cat, 1, maxn);
        }
    } else if(g[x] == 1) {
        auto it = g.lower_bound(x);
        if (it != g.begin()) {
            it--;
            update(x - (it -> first), rt, x, 1, maxn);
          
        } else {
            update(2e9, rt, x, 1, maxn);
        }
    }
  
}
  
int ask(int x) {
    auto it = g.upper_bound(x / 2);
    if (it == g.end()) return 2e9;
    if (it -> second > 1) return it -> first;
    if (it != g.begin()) {
        int cat = it -> first;
        it--;
        cat += it -> first;
        if (cat > x) {
            it++;
            return it -> first;
        }
        it++;
    }
    it++;
    if (it != g.end()) {
        return it -> first;
    }
    return 2e9;
}
  
  
  
  
int main () {
    scanf("%d", &q);
    for (int i = 0; i <= 2000000; i++) {
        tree[i].sum = INT_MAX;
        tree[i].l = tree[i].r = 0;
    }
    maxn = 1e9 + 7;
    while (q--) {
        int op, x;
        scanf("%d %d", &op, &x);
        if (op == 1) {
            add(x);
        } else if (op == 2) {
            deleate(x);
        } else if (op == 3) {
    
            int ans = query(rt, ask(x), maxn, 1, maxn);
       
            if (ans < x) puts("Yes");
            else puts("No");
        }
    }
}
posted @ 2020-07-17 00:56  ccsu_zhaobo  阅读(81)  评论(0编辑  收藏  举报