https://pintia.cn/problem-sets/994805342720868352/problems/994805417945710592
本题的一个最大的难点,就是如何给一个动态的区间内快速的找到中间值。
可以很容易的想到用set,因为它插入是有序的。但是set是不可以存重复的值的,于是可以想到用multiset。
但是写了一半,发现找中间迭代器不是太会。
于是看了一下柳神的做法,真的秒用树状数组+二分 碰巧的是昨天刚做了和这道题几乎一模一样做法的题。
于是快速的做了出来。
这里的数据范围不会超过1e5 且都是正整数 所以可以用树状数组来维护前缀。
然后二分找中间值。
#includeusing namespace std; const int N=1e5+10; int tr[N],n; stack st; int lowbit(int x){return x&(-x);} void add(int x,int c) {for(int i=x;i >1; if(sum(mid)>=len) r=mid; else l=mid+1; } return l; } int main(void) { cin>>n; while(n--) { string op; cin>>op; if(op=="Pop") { if(st.size()) { int temp=st.top(); st.pop(); cout< >x; st.push(x); add(x,1); }else { if(st.size()) cout< y总写的multiset做法。其实本题见有的大佬用map来维护中间值也是很秀,但是感觉有点复杂。
#include#include #include #include using namespace std; stack stk; multiset up, down; void adjust() { while (up.size() > down.size()) { down.insert(*up.begin()); up.erase(up.begin()); } while (down.size() > up.size() + 1) { auto it = down.end(); it -- ; up.insert(*it); down.erase(it); } } int main() { int n; scanf("%d", &n); char op[20]; while (n -- ) { scanf("%s", op); if (strcmp(op, "Push") == 0) { int x; scanf("%d", &x); stk.push(x); if (up.empty() || x < *up.begin()) down.insert(x); else up.insert(x); adjust(); } else if (strcmp(op, "Pop") == 0) { if (stk.empty()) puts("Invalid"); else { int x = stk.top(); stk.pop(); printf("%dn", x); auto it = down.end(); it -- ; if (x <= *it) down.erase(down.find(x)); else up.erase(up.find(x)); adjust(); } } else { if (stk.empty()) puts("Invalid"); else { auto it = down.end(); it -- ; printf("%dn", *it); } } } return 0; }



