PAT 1017Stack (30)

来源:互联网 发布:网络舆情监控的重要性 编辑:程序博客网 时间:2024/05/18 00:46

思路

  • 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.htmlstruct 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