PAT 1017 Stack (30)
2016-07-25 10:50
344 查看
思路
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; }
相关文章推荐
- Codeforces Round #301 (Div. 2) -- D. Bad Luck Island (概率DP)
- C#开放和封闭原则
- Android使用绘图Path总结
- 如何通过新浪微博和QQ空间获取精准客户
- JS继承
- 设计模式之门面模式
- Spark的Master分析3(Master状态改变机制分析)
- MyEclipse10.5-10.6-10.7导出war包报错问题
- 数据库进阶之数据库索引
- Cisco Port-Channel 设置端口捆绑方法
- linux下查看动态链接库依赖关系的命令 x86: ldd *.so arm: arm-linux-readelf -d *.so 实际例子: 以项目中用到的库librtsp.so分析: lijun@ubuntu:~/workspace$ arm-hisiv100nptl-linux-ld -d librtsp.so arm-hisiv100nptl-linux-ld:
- PHP基本知识收集
- PAT(B) - 1028. 人口普查(20)
- 利用流计算实时检测网络威胁
- 数据库进阶之数据库范式
- Raspberry Pi的GStreamer配置
- 关于win7或是winx的DNS异常处理
- 如何使Unity+vuforia做出来的模型导入到Android手机中能够实现阴影效果
- 布局被底部虚拟按键遮住
- ionic项目相关的操作命令