生活随笔
收集整理的這篇文章主要介紹了
HDU-5249 KPI(STL or 权值线段树)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
Problem Description
你工作以后, KPI 就是你的全部了. 我開發了一個服務,取得了很大的知名度。數十億的請求被推到一個大管道后同時服務從管頭拉取請求。讓我們來定義每個請求都有一個重要值。我的KPI是由當前管道內請求的重要值的中間值來計算。現在給你服務記錄,有時我想知道當前管道內請求的重要值得中間值。
Input
有大約100組數據。
每組數據第一行有一個n(1≤n≤10000),代表服務記錄數。
接下來有n行,每一行有3種形式
“in x”: 代表重要值為x(0≤x≤109)的請求被推進管道。
“out”: 代表服務拉取了管道頭部的請求。
"query: 代表我想知道當前管道內請求重要值的中間值. 那就是說,如果當前管道內有m條請求, 我想知道,升序排序后第floor(m/2)+1th 條請求的重要值.
為了讓題目簡單,所有的x都不同,并且如果管道內沒有值,就不會有"out"和"query"操作。
Output
對于每組數據,先輸出一行
Case #i:
然后每一次"query",輸出當前管道內重要值的中間值。
Sample Input
6
in 874
query
out
in 24622
in 12194
query
Sample Output
Case #1:
874
24622
思路
- 權值線段樹:更普通的線段樹差不多將元素存在對應區間的位置上,例如5就存在父節點(l == r == 5)的節點上,這樣就能查找區間第K大的元素。
- 用兩個set(內部遞增排序)模擬,添加和刪除操作之后都要保持左set的長度(m/2+1),這樣方便詢問的時候直接給出答案,而且不容易亂
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define maxn 10006
#define mid ((l + r) >> 1)
#define lc rt<<1
#define rc rt<<1|1
using namespace std
;map
<int, int> m1
;
map
<int, int> m2
;
int seg
[maxn
<< 2];
int a
[maxn
];void pushup
(int rt
) {seg
[rt
] = seg
[lc
] + seg
[rc
];
}void insert
(int rt
, int l
, int r
, int x
, int op
) {if (l
== r
) {seg
[rt
] += op
;return;}if (mid
>= x
) insert(lc
, l
, mid
, x
, op
);else insert(rc
, mid
+1, r
, x
, op
);pushup(rt
);
}int query(int rt
, int l
, int r
, int k
) {if (l
== r
) return l
;if (seg
[lc
] >= k
) return query(lc
, l
, mid
, k
);else return query(rc
, mid
+1, r
, k
- seg
[lc
]);
}
int main() {
#ifndef ONLINE_JUDGE
#endifint n
, d
, Case
= 1;char s
[10];while (scanf("%d", &n
) != EOF) {printf("Case #%d:\n", Case
++);mem(seg
, 0);priority_queue
<int> que
;queue
<int> que2
;m1
.clear();m2
.clear();for (int i
= 0; i
< n
; ++i
) {scanf("%s", s
);switch (s
[0]) {case 'i':scanf("%d", &a
[i
]);que
.push(a
[i
]);break;case 'o':a
[i
] = -1;break;case 'q':a
[i
] = -2; break;}}int pos
= que
.size();while (!que
.empty()) {m1
[que
.top()] = pos
;m2
[pos
] = que
.top();que
.pop();pos
--;}for (int i
= 0; i
< n
; ++i
) {if (a
[i
] >= 0) {insert(1, 1, n
, m1
[a
[i
]], 1);que2
.push(a
[i
]);}else if (a
[i
] == -1) {insert(1, 1, n
, m1
[que2
.front()], -1);que2
.pop();}else {pos
= query(1, 1, n
, que2
.size()/2 + 1);printf("%d\n", m2
[pos
]);}}}return 0;
}
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, n) for (int i = a; i < n; ++i)
#define maxn 100005
using namespace std
;set
<int> st1
, st2
;
queue
<int> que
; int main() {
#ifndef ONLINE_JUDGE
#endifchar s
[10];int n
, d
, m
, Case
= 0;while (scanf("%d", &n
) != EOF) {printf("Case #%d:\n", ++Case
);while (!que
.empty()) que
.pop();st1
.clear();st2
.clear(); m
= 0;for (int i
= 0; i
< n
; ++i
) {scanf("%s", s
);if (s
[0] == 'i') {scanf("%d", &d
);if (st1
.empty() || *st1
.rbegin() > d
) st1
.insert(d
);else st2
.insert(d
);que
.push(d
);m
++;}else if (s
[0] == 'q') {printf("%d\n", *st1
.rbegin());}else {int tmp
= que
.front();que
.pop();if (st1
.find(tmp
) != st1
.end()) st1
.erase(tmp
);else st2
.erase(tmp
);m
--;}while (m
> 0 && st1
.size() > m
/2 + 1) {d
= *st1
.rbegin();st2
.insert(d
);st1
.erase(d
);}while (m
> 0 && st1
.size() < m
/2 + 1) {d
= *st2
.begin();st1
.insert(d
);st2
.erase(d
);}}}return 0;
}
總結
以上是生活随笔為你收集整理的HDU-5249 KPI(STL or 权值线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。