PAT 1017 Stack (30)

思路

  • 1.蛋疼菊紧,思路什么的理清了,答案还不正确,下回再查好了。
  • 2.其实本来可以用一个数组a[]来记录每个值出现的次数(范围从0 – 10^5的个数),然后统计和就能很方便的求出中值了,但是由于数组太大,这样遍历即使是o(n)也受不了。
  • 3.所以接下来这个树状数组的目的就是为了方便求前n项和,注意这里存的是c[],而不是a[]了,俩者的差别看这篇博客。http://www.cppblog.com/menjitianya/archive/2015/11/02/212171.html
  • 4.多写一点吧,重点1.理解lowbit(),重点2.理解Ci = sum{ A[j] | i - 2^k + 1 <= j <= i }。重点3.理解sum(i)= sum( i - lowbit(i) ) + C[i]。即可以用迭代或者递归的方法求sum了,而且速度很快,这样对于找中值就很方便了。

我出错的一些点

  • 1.原来是i要从pos开始。。。omg,注意哪些要更新。
  • 2.上面那个>=,要不要取=要看下面这个(l,half),显然=value是也是(l,half)这个范围内的。
  • 3.switch要记得加break;

代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
#include<string>
using namespace std;
//其实本来可以用一个数组a[]来记录每个值出现的次数(范围从0 -- 10^5的个数),然后统计和就能很方便的求出中值了,但是由于数组太大,这样遍历即使是o(n)也受不了
//所以接下来这个树状数组的目的就是为了方便求前n项和,注意这里存的是c[],而不是a[]了,俩者的差别看这篇博客http://www.cppblog.com/menjitianya/archive/2015/11/02/212171.html
struct tree
{
    static const int MAXN = 100001;
    //不能直接声明
    //vector<int> a(MAXN,0);
    vector<int> a;
    tree() :a(vector<int>(MAXN, 0)){}
    int lowbit(int t)
    {
        return t&(-t);
    }
    //虽然很多,但是log()下来次数就很低了
    //额,下面可以写的更简单
    //void add(int pos, int val)
    //{
    //  //原来是i要从pos开始。。。omg
    //  for (int i = pos; i < MAXN; i += lowbit(pos))
    //  {
    //      if (val == 1)
    //          a[i]++;
    //      else if (val == -1 && a[i]>0)
    //          a[i]--;

    //  }
    //}
    //我上面错在哪?
    void add(int t, int d)
    {
        while (t <= MAXN)
        {
            a[t] += d;
            t += lowbit(t);
        }
    }
    //主要就是利用下面的这个性质
    //Ci  =  sum{ A[j] |  i - 2^k + 1 <= j <= i }    (帮助理解:将j的两个端点相减+1 等于2^k),并且左边那边的i-2^k后为0了,即加到左边的那项就可以了
    //sum(i)= sum( i - lowbit(i) ) + C[i]
    int getsum(int k)
    {
        //return k ? getsum(k - lowbit(k)) + a[k] : 0;;
        int s = 0;
        for (int i = k; i; i = i - lowbit(k))
        {
            s += a[i];
        }
        return s;
    }
    //为了方面计算,找中值或者找第几个值都从0开始,这样,例如0,1,2的中值就是2/2=1,就是1,这里是讨论value的取值问题。
    int findmedian(int value,int l=0,int h=MAXN-1)//可以先赋初值
    {
        if (l == h)
            return l;
        int half = (h + l) / 2;
        if (getsum(half) >= value)
        {
            //上面那个>=,要不要取=要看下面这个(l,half),显然=value是也是(l,half)这个范围内的。
            return findmedian(value, l, half);
        }
        else
        {
            return findmedian(value, half+1, h);
        }
    }
    /*void show()
    {
        cout << "trees.a:";
        for (int i = 0; i < 10; i++)
        {
            cout << a[i] << " ";
        }
        cout << endl;
    }*/
};
tree trees;
int main()
{
    stack<int> a;
    int n; string b;int c;
    cin >> n;
    while (n--)
    {
        //cout << "aaa" << endl;
        cin >> b;
        switch (b[1])
        {
        case 'o':
            if (a.empty())
                cout << "Invalid" << endl;
            else
            {
                int d = a.top();
                a.pop();
                cout << d << endl;
                trees.add(d, -1);
            }
            //switch要记得加break;
            /*cout << "o:";
            trees.show();*/
            break;
        case 'e':
            if (a.empty())
                cout << "Invalid" << endl;
            else
            {
                int mid = (int)(a.size() + 1) / 2;
                //cout << "mid:" << mid << endl;;
                int d = trees.findmedian(mid);
                cout << d<<endl;
            }
            /*cout << "e:";
            trees.show();*/
            break;
        case 'u':
            cin >> c;
            a.push(c);
            trees.add(c, 1);
            /*cout << "u:";
            trees.show();*/
            break;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值