羅区P2073の花
説明
これらの花は美しく、それぞれの花が美しい値Wを持ち、価格はCです。
暁明は、彼が内側に花を追加し続け、空の花束を持つようになりました。彼は次の操作があります。
操作意味
1 WC Wの美しい値、フラワーCの価格を追加
3暁明は、花の現在の最も安い花束があまりにも安いと思いますが、それは赤には適していませんので、安い花を削除します。
2暁明は、現在最も高価な花のブーケが、彼は自分のお金が、その最も高価な花を削除することを悩んでいたあまりにも高価だと思います。
-1追加や削除が完了し、花束を荷造りを始めます
削除費やしていない場合は、削除をスキップします。
あなたは花の価格は花価格の花束で繰り返された追加した場合、これは花の花束に参加することはできません。
暁明は、あなたがパッケージング花束の最初に計算プログラムを、書くため、すべての花の美しい花束の値の合計値、および合計金額暁明は、花束のために支払う必要があります。
入力
- -1で終了操作のいくつかのライン、。
出力
- ライン、すべての美しい値の花の花束の包装花束の先頭に正の整数の和で区切られた2つのスペース。そして、暁明は、花束のために合計金額を支払う必要。
サンプル入力
1 1 1 1 2 5 2 1 3 3 3 1 5 2 -1
サンプル出力
8 5
データサイズ
データの20%を、オペランド<= 100,1 <= C <= 1000、W。
すべてのデータのために、オペランド<= 100000,1 <= C <= 1000000、W。
ソリューション:
- バランスのとれたツリー。
- この問題は、まだ比較的、それをテンプレートです。
- 私はこの質問2と3は、独創的なソリューションを比較するために使用することができます動作することを好みます。接尾前駆体の機能が付属し、最大/軽量を探します!サフィックス-infを見つけるために最小重量を探して、接頭辞INFを見つけるための最大重量を探します。
- だから、K-プライオリティキューを開いたり、大きな発見する必要はありません!
- 気づいた、バランスの取れたツリーを使用して多くの質問は、接頭辞/接尾機能の使用に柔軟です!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define N 100005
#define inf 0x7fffffff
using namespace std;
struct T {int l, r, v1, v2, dat;} t[N];
int op, root, tot, ans1, ans2;
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
int New(int v1, int v2)
{
t[++tot].v1 = v1, t[tot].v2 = v2;
t[tot].dat = rand();
return tot;
}
void zig(int &y)
{
int x = t[y].l;
t[y].l = t[x].r, t[x].r = y, y = x;
}
void zag(int &x)
{
int y = t[x].r;
t[x].r = t[y].l, t[y].l = x, x = y;
}
void insert(int &p, int v1, int v2)
{
if(!p) {p = New(v1, v2); return;}
if(v1 == t[p].v1) return;
if(v1 < t[p].v1)
{
insert(t[p].l, v1, v2);
if(t[t[p].l].dat > t[p].dat) zig(p);
}
else
{
insert(t[p].r, v1, v2);
if(t[t[p].r].dat > t[p].dat) zag(p);
}
}
bool find(int p, int val)
{
if(!p) return 0;
if(t[p].v1 == val) return 1;
if(val < t[p].v1) return find(t[p].l, val);
else return find(t[p].r, val);
}
int preNext(int op, int val)
{
int ans = op == 0 ? 2 : 1, p = root;
while(p)
{
if(t[p].v1 == val)
{
if(!op && t[p].l)
{
p = t[p].l;
while(t[p].r) p = t[p].r;
ans = p; break;
}
else if(!op) break;
if(op && t[p].r)
{
p = t[p].r;
while(t[p].l) p = t[p].l;
ans = p; break;
}
else if(op) break;
}
if(!op && t[p].v1 < val && t[p].v1 > t[ans].v1) ans = p;
if(op && t[p].v1 > val && t[p].v1 < t[ans].v1) ans = p;
p = val < t[p].v1 ? t[p].l : t[p].r;
}
return t[ans].v1;
}
void erase(int &p, int val)
{
if(!p) return;
if(val == t[p].v1)
{
if(t[p].l || t[p].r)
{
if(!t[p].r || t[t[p].l].dat > t[t[p].r].dat) zig(p), erase(t[p].r, val);
else zag(p), erase(t[p].l, val);
}
else p = 0;
return;
}
val < t[p].v1 ? erase(t[p].l, val) : erase(t[p].r, val);
}
void dfs(int p)
{
if(!p) return;
if(t[p].v1 != inf && t[p].v1 != -inf) ans1 += t[p].v1;
if(t[p].v2 != inf && t[p].v2 != -inf) ans2 += t[p].v2;
dfs(t[p].l), dfs(t[p].r);
}
int main()
{
New(inf, inf), New(-inf, -inf), root = 1, t[1].l = 2;
while(scanf("%d", &op) == 1)
{
if(op == -1) break;
if(op == 1)
{
int bea = read(), cos = read();
if(!find(root, cos)) insert(root, cos, bea);
}
else if(op == 2)
{
int cos = preNext(0, inf);
if(cos != -inf) erase(root, cos);
}
else if(op == 3)
{
int cos = preNext(1, -inf);
if(cos != inf) erase(root, cos);
}
}
dfs(root);
cout << ans2 << ' ' << ans1 << endl;
return 0;
}