分析:
私はこの質問に何日間も苦労し、午後もバグを探して気が変わり、ついにそれを思いつきました。非常に有毒な質問は、3つのタイプのラインセグメントツリー、4つの操作の1つの質問に相当します。
①xの長さの最小間隔とカバーを見つけます。
②点xが存在する間隔を削除します。
③x番目の区間の開始位置を見つけます。
④すべての間隔をクリアします。
分析が見つかりました:
④は複数回操作すること②
②の場合:①の各間隔を記録し、逆に操作する必要があります①
①に関して:インターバル間にオーバーラップがないため、遅延配列に下向きの更新、または上向きの更新を保存する必要がなく、これを知ることでコードを簡略化できます。さらに、空白の間隔の格納は、当初は最大間隔の開始点であると考えられていましたが(後で愚かで実現不可能であることが判明)、クエリに便利な従来の左および右の最大間隔に変更されました。
③について:実は最大の問題を見つけることです(STLでバイナリ関数を使って見つけることができるというブログがあるようですが、はっきりしません)とにかく、元の線分ツリーにパラメータを追加して区間内の目標数を記録しましたいくら、基本的なポイント操作。
最後に、この質問を発声する複雑な操作は本当に忍耐力です。少しの間違いがあれば、バグを見つけるために数百行のコードがあり、複数の入力と出力のセットがあり、各グループ間のキャリッジリターンもサービスです。特にアイドルでない場合の個人的なアドバイス現時点ではこの質問をしないようにしてください。本当にクラッシュする可能性がありますo(≧口≦)o
コード:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200050;
const int inf = 0x7fffffff;
struct Node
{
int l;
int r;
};
int n, m;
int mmax[maxn], lmax[maxn], rmax[maxn], belong[maxn], have[maxn];
int x, ql, qr, qv, presum;
vector<Node>neww;
set<int>reset;
void init()
{
neww.clear();
reset.clear();
}
void build(int o, int l, int r)
{
lmax[o] = rmax[o] = mmax[o] = r - l + 1;
belong[o] = have[o] = 0;
if (l == r)return;
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1 | 1, mid + 1, r);
}
void update(int o, int l, int r)
{
if (ql <= l&&r <= qr)
{
belong[o] = qv;
if (qv == 0)lmax[o] = rmax[o] = mmax[o] = r - l + 1;
else lmax[o] = rmax[o] = mmax[o] = 0;
return;
}
int mid = (l + r) >> 1, lo = o << 1, ro = o << 1 | 1;
if (ql <= mid)update(lo, l, mid);
if (qr>mid) update(ro, mid + 1, r);
lmax[o] = lmax[lo];
if (lmax[lo] == mid - l + 1)lmax[o] += lmax[ro];
rmax[o] = rmax[ro];
if (rmax[ro] == r - mid)rmax[o] += rmax[lo];
mmax[o] = max(rmax[lo] + lmax[ro], max(mmax[lo], mmax[ro]));
}
void add(int o, int l, int r)
{
if (l == r)
{
have[o] = qv ? 1 : 0;
return;
}
int mid = (l + r) >> 1;
if (ql <= mid)add(o << 1, l, mid);
else add(o << 1 | 1, mid + 1, r);
have[o] = have[o << 1] + have[o << 1 | 1];
}
int query_new(int o, int l, int r)
{
if (l == r)return l;
int mid = (l + r) >> 1, lo = o << 1, ro = o << 1 | 1;
if (mmax[lo] >= x)return query_new(lo, l, mid);
if (rmax[lo] + lmax[ro] >= x)return mid - rmax[lo] + 1;
return query_new(ro, mid + 1, r);
}
int query_free(int o, int l, int r)
{
if (belong[o])return belong[o];
if (l == r)return 0;
int mid = (l + r) >> 1;
if (x <= mid)return query_free(o << 1, l, mid);
return query_free(o << 1 | 1, mid + 1, r);
}
int query_get(int o, int l, int r)
{
if (l == r)return l;
int mid = (l + r) >> 1, lo = o << 1, ro = o << 1 | 1;
if (presum + have[lo] >= x)return query_get(lo, l, mid);
presum += have[lo];
return query_get(ro, mid + 1, r);
}
void delet()
{
qv = 0;
update(1, 1, n);
add(1, 1, n);
}
int main()
{
while (~scanf("%d%d", &n, &m))
{
build(1, 1, n);
init();
while (m--)
{
char op[10];
scanf(" %s", op);
if (op[0] == 'N')
{
scanf("%d", &x);
if (mmax[1]<x)printf("Reject New\n");
else
{
ql = query_new(1, 1, n);
qr = ql + x - 1;
neww.push_back((Node){ ql, qr });
qv = neww.size();
update(1, 1, n);
add(1, 1, n);
printf("New at %d\n", ql);
}
}
else if (op[0] == 'F')
{
scanf("%d", &x);
qv = query_free(1, 1, n);
if (qv == 0)printf("Reject Free\n");
else
{
reset.insert(qv);
ql = neww[qv - 1].l;
qr = neww[qv - 1].r;
delet();
printf("Free from %d to %d\n", ql, qr);
}
}
else if (op[0] == 'G')
{
scanf("%d", &x);
if (have[1]<x)printf("Reject Get\n");
else
{
presum = 0;
printf("Get at %d\n", query_get(1, 1, n));
}
}
else if (op[0] == 'R')
{
for (int len = neww.size(), i = 0; i<len; i++)
{
if (reset.find(i + 1) == reset.end())
{
ql = neww[i].l;
qr = neww[i].r;
delet();
}
}
printf("Reset Now\n");
init();
}
}
printf("\n");
}
return 0;
}