题意:
模拟一个栈,要求可以输出中位数。
思路:
这题还是有点意思,看题意就知道会卡时间复杂度,想着用multiset试一下发现果然有几个点过不去,后面就没想出来。实际这题应该用树状数组做:
- Push x:就update(x,1),就是树状数组的区间更新,c[i]+=1,说明值为i的数出现并更新与其相关的数
- Pop:就update(x,-1),c[i]-=1,将值为i的数以及和它相关的数更新
- PeekMedian:用二分查找中位数,每次用getsum(i)求得前i个数中实际出现了几个数,与中位数k比较即可
#include<iostream> #include<string> #include<vector> #include<map> #include<set> #include<stack> #include<cmath> #include<string.h> #include<sstream> #include<functional> #include<algorithm> #define lowbit(i) ((i)&(-i)) using namespace std; const int INF = 0xfffff; const int maxn = 100050; stack<int> s; int c[maxn]; void update(int x, int v) { for (int i = x; i < maxn; i += lowbit(i)) c[i] += v; } int getsum(int x) { int sum = 0; for (int i = x; i >= 1; i -= lowbit(i)) sum += c[i]; return sum; } void peekMid() { int left = 1, right = maxn, k = (s.size() + 1) / 2; while (left < right) { int mid = (left + right) / 2; if (getsum(mid) >= k) right = mid; else left = mid + 1; } printf("%d\n", left); } int main() { int n,temp; scanf("%d", &n); char str[15]; while (n--) { scanf("%s", str); if (str[1] == 'u') { scanf("%d", &temp); s.push(temp); update(temp, 1); } else if (str[1] == 'o') { if (!s.empty()) { temp = s.top(); s.pop(); update(temp, -1); printf("%d\n", temp); } else printf("Invalid\n"); } else { if (!s.empty()) { peekMid(); } else printf("Invalid\n"); } } return 0; }