PAT-1057. Stack (30)--树状数组

今天新学了一个知识,叫做线状数组,主要应用领域

1,数据频繁更新

2,求解某一段区间的和

以上产景情况下可以使用线状数组,更新某一个数据和求某一段时间之和时间复杂度都是Log(N) {常规情况是O(1)和O(N)}

线状数组和RMQ差不多,都可以再Log(N)时间复杂度内求解某一段区间的长度,线状数组额实现方式更为简单,更为方便

以下可以当做线段树的模板

主要函数有lowbit给定制定数字二进制下在末尾为0的个数。

Update更新某一节点的值。

getsum求解某一区间的值

Update是从叶子到根顶部跟新,getsum是从上至下更新,父子节点的差距就是lowbit(n);

求解一段区间的和为什么可以用来求解中位数呢?

声明数组,初始化为0,当某个数出现的时候,比如10,那么tree[10]=1; 比如查找1-100就可以知道100以内有多少个数据存在了。

有一个问题比如

1 2 3 4 5 6 7 8 9 10

0 0 0 1 0 0 1 0 1 0

那么求解1-4的和为1

求解1-5也为1,求解1-6也为1.那么我怎么知道是哪一个作为?

(编码的时候只有当l==r时候才返回值,也就是区间左右都相等的时候才返回值,否则不返回值,如果是getsum(mid)==mid不做特殊处理。最初写成返回return mid

还是树状数组理解不够深。。待续。。。

// 1057.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<string>
#include<stack>
using namespace std;

#define MAX 100010

stack<int> s;

int tree[MAX]={0};

int lowbit(int ind)
{
	return ind & -ind;
}

void update(int ind,int val)
{
	while(ind<=MAX)
	{
		tree[ind]+=val;
		ind+=lowbit(ind);
	}
}

int getsum(int ind)
{
	int sum=0;
	while(ind>0) //not >=0
	{
		sum+=tree[ind];
		ind-=lowbit(ind);
	}
	return sum;
}

int findmid(int number,int l,int r)
{
	if(l==r)
		return l;
	int mid=(l+r)/2;
	int sum=getsum(mid);
	if(sum<number)
	{
		return findmid(number,mid+1,r);
	}
	else
	{
		return findmid(number,l,mid);
	}
	/*
	  最后return mid会出错
 	*/
}

int main()
{
	int num;
	string op;
	char op_name[15];
	int tmp;
	freopen("1057.txt","r",stdin);
	while(scanf("%d",&num)!=EOF)
	{
       for(int i=0;i<num;i++)
	   {
		   scanf("%s",op_name);
		   op=string(op_name);
		   if(op=="Pop")
		   {
			   if(!s.empty())
			   {
				   tmp=s.top();
				   update(tmp,-1);
				   printf("%d\n",tmp);
				   s.pop();
			   }
			   else
			   {
				   printf("Invalid\n");
			   }
		   }
		   if(op=="Push")
		   {
			   scanf("%d",&tmp);
			   s.push(tmp);
			   update(tmp,1);
		   }
		   if(op=="PeekMedian")
		   {
			   int size=s.size();
			   if(size==0)
			   {
				   printf("Invalid\n");
				   continue;
			   }
			   if(size%2==0)
				   size=size/2;
			   else
				   size=(size+1)/2;

			   int mid=findmid(size,1,MAX);

			   printf("%d\n",mid);
		   }
	   }
	}
	return 0;
}

  

时间: 2024-08-10 00:07:35

PAT-1057. Stack (30)--树状数组的相关文章

PAT甲题题解-1057. Stack (30)-树状数组

不懂树状数组的童鞋,正好可以通过这道题学习一下树状数组~~百度有很多教程的,我就不赘述了 题意:有三种操作,分别是1.Push key:将key压入stack2.Pop:将栈顶元素取出栈3.PeekMedian:返回stack中第(n+1)/2个小的数 建立一个栈来模拟push和pop,另外还需要树状数组,来统计栈中<=某个数的总个数不了解树状数组的建议学习一下,很有用的.树状数组为c,有个虚拟的a数组,a[i]表示i出现的次数sum(i)就是统计a[1]~a[i]的和,即1~i出现的次数当我要

1057. Stack (30) - 树状数组

题目例如以下: Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are

PAT甲级1057 Stack【树状数组】【二分】

题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805417945710592 题意:对一个栈进行push, pop和找中位数三种操作. 思路: 好久没写题.感觉傻逼题写多了稍微有点数据结构的都不会写了. pop和push操作就不说了. 找中位数的话就二分去找某一个数前面一共有多少小于他的数,找到那个小于他的数刚好等于一半的. 找的过程中要用到前缀和,所以自然而然就应该上树状数组. 要注意树状数组的界应该是1e5而

PAT 1057. Stack (30)

题目地址:http://pat.zju.edu.cn/contests/pat-a-practise/1057 用树状数组和二分搜索解决,对于这种对时间复杂度要求高的题目,用C的输入输出显然更好 #include <cstdio> #include <string> #include <vector> #include <stack> using namespace std; const int NUM=100001; struct TreeArray {

PAT1057 Stack(树状数组+倍增)

目录 题目大意 题目分析 题目大意 要求维护一个栈,提供压栈.弹栈以及求栈内中位数的操作(当栈内元素\(n\)为偶数时,只是求第\(n/2\)个元素而非中间两数的平均值).最多操作100000次,压栈的数字\(key\)范围是[1,100000]. 题目分析 前两个操作用\(stack\)就好. 求中位数.暴力做法即使用上优先队列也是稳稳的超时.考虑树状数组. 压栈时,将\(key\)值对应的位置加1.弹栈减1. 求中位数,可以二分求出\(sum[1:p]==(n+1)/2\)最小的\(p\),

POJ1990--POJ 1990 MooFest(树状数组)

Time Limit: 1000MSMemory Limit: 30000K Total Submissions: 8141Accepted: 3674 Description Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a social gathering of cows from around the world. MooFest involves a variety of e

PAT 甲级1057 Stack (30 分)(不会,树状数组+二分)*****

1057 Stack (30 分) Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). No

PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车连续多次进入,只取最后一个 2.如果一个车连续多次出去,只取第一个 3.一个车可能出入校园内好几次,停留时间取总和 实际上题目就是让我们求某个时间段内的车辆总和,时间段其实就相当于一个区间,区间求和的话,很快就联想到树状数组和线段树.然而怎么将时间段和区间联系起来呢,那就存储出现在记录和询问里的所有

PAT (Advanced Level) 1057. Stack (30)

树状数组+二分. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<map> #include<queue> #include<string> #include<stack> #include<vector> using namespace