制限時間:C / C ++ 2秒、その他の言語4秒
スペース制限:C / C ++ 262144K、その他の言語524288K
64ビットIO形式:%lld
タイトル説明
マルチセットMS {MS} MSおよびq {q} q操作が与えられます。MS {MS} MSは最初は空であり、操作には次の3つのタイプがあり
ます。1。要素x {x} xをMS {MS} MSに挿入します
。2。要素x {x} xをMS {から消去します。 MS} MS3
。整数x {x} xが与えられた場合、長さa、b、x {aの3つのセグメントであるMS {MS} MSで2つの要素a、b {a、b} a、bを選択できるかどうかを判断します。 、b、x} a、b、xは非縮退三角形を作成できます。
説明を入力してください:
最初の行には整数q(1≤q≤2×105)q〜(1 \ leq q \ leq 2 \ times 10 ^ 5)q(1≤q≤2×105)が含まれ、演算の数を示します。
次のq {q} q行には、それぞれ2つの整数op、x(op∈{1,2,3}、1≤x≤109)op、x〜(op \ in \ {1,2,3 \}、1 \ leq x \ leq 10 ^ 9)op、x(op∈{1,2,3}、1≤x≤109)、操作を示し
ます1. op = 1 {op = 1} op = 1の場合、要素x {x} xをMS {MS} MS2に挿入し
ます。op= 2 {op = 2} op = 2の場合、要素x {x} xをMS {MS} MSから消去すると、少なくとも1つあることが保証されます。現在MS {MS} MSのx {x}
x3。op= 3 {op = 3} op = 3の場合、MS {MS}で2つの要素a、b {a、b} a、bを選択できるかどうかを判断します。長さa、b、x {a、b、x} a、b、xの3つのセグメントが三角形を作ることができるMS
出力の説明:
クエリごとに、答えが「はい」の場合は「はい」、答えが「いいえ」の場合は「いいえ」という文字列を含む1行を出力します。
例1
入る
コピー81 1 3 1 1 1 3 2 3 1 1 2 2 1 3 1
8 1 1 3 1 1 1 3 2 3 1 1 2 2 1 3 1
出力
复制No No Yes No
いいえ いいえ はい いいえ
本旨:
セットの場合、番号Xの追加と番号Xの削除の2つの操作があります。同時に、現在のクエリXと三角形を形成するために、セットに2つの番号aとbがあるかどうかを確認するクエリ操作があります。
解決:
三角形の3つの辺a、b、cが減少しない順序で配置されていると仮定すると、三角形の性質に応じてa + b> cを知ることができます。
1. Xがcの場合、明らかにaとbは可能な限り大きくなります。
2. Xがbの場合、明らかにaは可能な限り大きく、cは可能な限り小さくなります。
3. Xがaの場合、aより大きいすべての数値から選択します。隣接する数値の差が最も小さい2つの数値の方が適しています。
要約すると、マルチセットとマップを使用して最初の2つのケースを維持し、ラインセグメントツリーを使用して2つの隣接する数値の差を維持します(xは大きく、動的オープニングは良好です)。場合によっては、等辺の三角形を形成したり、Xでリストされたケースに先行、後続などがないなど、特別な判断が必要になります。詳細はまだかなり多く、調整に時間がかかります。
受け入れられたコード
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1e6 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }
int mi[N * 60], ls[N * 60], rs[N * 60];
unordered_map <int, int> rt, mp;
multiset <int> st;
int idx, n = 1e9;
void Pushdown(int o) {
if (!ls[o])
ls[o] = ++idx, mi[idx] = INF;
if (!rs[o])
rs[o] = ++idx, mi[idx] = INF;
}
void Update(int o, int L, int R, int x, int val) {
if (L == R && L == x) {
mi[o] = val;
return;
}
Pushdown(o);
int mid = (L + R) >> 1;
if (mid >= x)
Update(ls[o], L, mid, x, val);
else
Update(rs[o], mid + 1, R, x, val);
mi[o] = min(mi[ls[o]], mi[rs[o]]);
}
int Ask(int o, int L, int R, int l, int r) {
if (L >= l && R <= r)
return mi[o];
Pushdown(o);
int mid = (L + R) >> 1, ans = INF;
if (mid >= l)
Min(ans, Ask(ls[o], L, mid, l, r));
if (mid < r)
Min(ans, Ask(rs[o], mid + 1, R, l, r));
return ans;
}
bool Bigest(int x) {
if (mp[x]) { // 有x
auto pre = st.lower_bound(x);
if (pre == st.begin())
return false;
return true;
}
else { // 无x
auto pre = st.lower_bound(x);
if (pre == st.begin()) // 无前驱
return false;
pre--;
if (pre == st.begin()) // 无前驱1
return false;
auto pre1 = pre;
pre1--;
if (*pre1 + *pre > x)
return true;
return false;
}
}
bool Pre(int x) {
auto pre = st.lower_bound(x);
if (pre == st.begin()) // 无前驱
return false;
return true;
}
bool Nxt(int x, int &ans) {
auto nxt = st.upper_bound(x);
if (nxt == st.end()) // 无后继
return false;
ans = *nxt;
return true;
}
bool Mid(int x) {
if (mp[x]) { // 有x
int nxt;
if (Pre(x))
return true;
if (Nxt(x, nxt)) {
if (x + x > nxt)
return true;
}
return false;
}
else { // 无x
auto nxt = st.upper_bound(x); // 后继
if (nxt == st.end())
return false;
auto pre = nxt;
if (pre == st.begin()) // 前驱
return false;
pre--;
if (*pre + x > *nxt)
return true;
return false;
}
}
bool Smallest(int x) {
if (mp[x]) {
auto nxt = st.upper_bound(x);
if (nxt == st.end())
return false;
if (2 * x > *nxt)
return true;
}
int c = Ask(rt[1], 1, n, x + 1, n);
if (c < x)
return true;
return false;
}
int main()
{
rt[1] = ++idx, mi[1] = INF; // 动态开点
int q;
cin >> q;
while (q--) {
int op, x, y;
sc("%d %d", &op, &x);
if (op == 1) { // 加入点X
mp[x]++, st.insert(x);
if (mp[x] == 1) { // 是集合中唯一的X
auto it = st.lower_bound(x);
if (it == st.begin()) // 无前驱
Update(rt[1], 1, n, x, INF);
else { // 有前驱,更新x差值
it--;
Update(rt[1], 1, n, x, x - *it);
}
it = st.upper_bound(x); // 后继
if (it != st.end()) {
if (mp[*it] == 1)
Update(rt[1], 1, n, *it, *it - x);
}
}
else // 差值为0
Update(rt[1], 1, n, x, 0);
}
else if (op == 2) { // 删除x
auto it = st.lower_bound(x);
st.erase(it), mp[x]--;
if (mp[x] == 1) { // 找前驱
auto it = st.lower_bound(x);
if (it == st.begin()) // 无前驱
Update(rt[1], 1, n, x, INF);
else {
it--;
Update(rt[1], 1, n, x, x - *it);
}
}
else if (!mp[x]) {
Update(rt[1], 1, n, x, INF);
if (st.empty())
continue;
auto it = st.upper_bound(x);
if (it == st.end()) // 无后继
continue;
if (it == st.begin()) { // 后继且无前驱
if (mp[*it] == 1)
Update(rt[1], 1, n, *it, INF);
}
else if (mp[*it] == 1) {
auto pre = it; pre--;
Update(rt[1], 1, n, *it, *it - *pre);
}
}
}
else {
if (SZ(st) <= 1) {
puts("No");
continue;
}
if (mp[x] >= 2) {
puts("Yes");
continue;
}
if (Bigest(x)) // X当作C
puts("Yes");
else if (Mid(x)) // X当作b
puts("Yes");
else if (Smallest(x)) // X当作a
puts("Yes");
else
puts("No");
}
}
return 0; // 改数组大小!!!用pair记得改宏定义!!!
}