# L3-002. 堆栈

200 ms

65536 kB

8000 B

Standard

Push key
Pop
PeekMedian

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop


Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

// 线段树求区域第K大值
#include <iostream>
#include <stack>
#include <string>
using namespace std;
struct node {
int left, right, value;
}tree[4 * 100005];

// i为当前操作的树节点的坐标，left，right为区间的范围。
void build(int i, int left , int right) {
tree[i].left = left;
tree[i].right = right;
tree[i].value = 0;
if (tree[i].left == tree[i].right)
return;
int mid = (tree[i].left + tree[i].right) / 2;
build(i * 2, left, mid);
build(i * 2 + 1, mid + 1, right);
}
// i为当前操作的树节点的坐标，left，rgiht为区间的范围，pos为出栈的值，这里的value为1就是push，-1为pop；
void update(int i, int left, int right, int pos, int value) {
if (tree[i].left == tree[i].right && tree[i].left == pos) {
tree[i].value += value;
return;
}
int mid = (tree[i].left + tree[i].right) / 2;
if (mid >= pos)
update(i * 2, left, mid, pos,value);
else
update(i * 2 + 1, mid + 1, right, pos,value);
tree[i].value = tree[i * 2].value + tree[i * 2 + 1].value;
}
// i为当前操作的树节点的坐标，left，rgiht为区间的范围，pos为出栈的值
// 这里查询第（N/2）或（N+1）/2 大的值
int query(int i, int left, int right, int pos) {
if (tree[i].left == tree[i].right)
return tree[i].left;
int mid = (tree[i].left + tree[i].right) / 2;
if (tree[i * 2].value >= pos)
query(i * 2, left, mid, pos);
else
// 如果查询的范围大于现在的范围了，需要把现在右边的范围里的值减掉
query(i * 2 + 1, mid + 1, right, pos - tree[i * 2].value);
}
int main()
{
//freopen("data.txt", "r", stdin);
stack<int> sta;
int N;
string str;
cin >> N;
// 先将线段树初始化
build(1, 0, 100005);
for (int i = 0; i < N; i++) {
int num;
cin >> str;
if (str == "Push") {
cin >> num;
sta.push(num);
update(1, 0, 100005, num, 1);
}
else if (str == "Pop")
if (sta.empty())
cout << "Invalid" << endl;
else {
cout << sta.top() << endl;
update(1, 0, 100005, sta.top(), -1);
sta.pop();
}
else {
if (sta.empty())
cout << "Invalid" << endl;
else {
int n = sta.size();
if (n % 2 == 0)
n /= 2;
else
n = (n + 1) / 2;
cout << query(1, 0, 100005, n) << endl;
}
}
}
return 0;
}

// 树状数组+二分查找
// getsum(x)的含义就是栈中不超过x的数有多少个
#include <iostream>
#include <stack>
#include <string>
#define max 100005
using namespace std;
int C[max] = { 0 };

// 树状数组的标准模版
int lowbit(int t) {
return t & (-t);
}

void update(int pos, int value) {
for (int i = pos; i < max; i += lowbit(i))
C[i] += value;
}

int getsum(int x) {
int sum = 0;
for (int i = x; i > 0; i -= lowbit(i))
sum += C[i];
return sum;
}

int main()
{
//freopen("data.txt", "r", stdin);
stack<int> sta;
int N;
string str;
cin >> N;
for (int i = 0; i < N; i++) {
int num;
cin >> str;
if (str == "Push") {
cin >> num;
sta.push(num);
update(num, 1);
}
else if (str == "Pop")
if (sta.empty())
cout << "Invalid" << endl;
else {
cout << sta.top() << endl;
update(sta.top(), -1);
sta.pop();
}
else {
if (sta.empty())
cout << "Invalid" << endl;
else {
int n = sta.size();
if (n % 2 == 0)
n /= 2;
else
n = (n + 1) / 2;
// 这里用二分查找
int left = 0, right = max;
while (left < right) {
int mid = (right + left) / 2;
if (getsum(mid) >= n)
right = mid;
else
left = mid + 1;
}
cout << left << endl;
}
}
}
return 0;
}

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客