Happy Triangle
Happy Triangle
题意:
给一个多重集和,你要q次操作
- 向多重集合里插入一个x。
- 向多重集合里删一个x(数据保证删除的数存在再集合中国)。
- 给你一个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");
}
}
}