文章目录
栈、队列与堆及练习题
前导知识
:
参考如下博文:
1. 后缀表达式(栈)
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int main(){
string a;
cin>>a;
stack<int> s;
int x=0,y=0;
for(int i=0;i<a.size();i++){
if(isdigit(a[i])) x=x*10+a[i]-'0'; /* 存在输入为两位数的情况 */
else if(a[i]=='.') s.push(x),x=0; /* 压入x,并更新x为0 */
else if(a[i]=='@') break; /* 终止符 */
else{
y=s.top(),s.pop();
x=s.top(),s.pop();
switch(a[i]){
case '*': s.push(x*y); break;
case '+': s.push(x+y); break;
case '-': s.push(x-y); break;
case '/': s.push(x/y); break;
}
x=0;
y=0;
}
}
cout<<s.top()<<'\n';
return 0;
}
2. 机器翻译(队列)
#include <iostream>
#include <queue>
using namespace std;
const int MAX_N = 1e5+5;
int n,m;
queue<int> q;
bool inq[MAX_N];
int main(){
cin>>m>>n;
int ans=0;
for(int i=1;i<=n;i++){
int t;
cin>>t;
if(!inq[t]){
ans++;
q.push(t);
inq[t]=true;
if(q.size()>m){
inq[q.front()]=false,q.pop();
}
}
}
cout<<ans;
return 0;
}
3. 世界杯(堆)
#include <iostream>
#include <queue>
using namespace std;
int a[4];
priority_queue<int> q[4];
int main(){
for(int i=0;i<4;i++)
cin>>a[i];
for(int i=0;i<4;i++){
for(int j=1;j<=a[i];j++){
int t;
cin>>t;
q[i].push(t);
}
}
int t;
cin>>t;
while(t--){
int b[4]={1};
for(int i=1;i<=3;i++)
cin>>b[i];
int sum=0;
for(int i=0;i<4;i++){
while(b[i]--){
sum+=q[i].top(),q[i].pop();
}
}
printf("%.2f\n",sum/11.0);
}
return 0;
}
4. [NOIP2003 普及组] 栈(卡特兰数+递推)
#include <iostream>
using namespace std;
int n;
int find_stack(int n){
if(n==0){
return 1;
}
if(n==1){
return 1;
}
int sum=0;
for(int i=0;i<n;i++){
sum+=find_stack(i)*find_stack(n-1-i);
}
return sum;
}
int main(){
cin>>n;
cout<<find_stack(n);
return 0;
}
5. 约瑟夫问题(循环队列)
#include <iostream>
#include <vector>
using namespace std;
int n,m;
vector<int> v;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
v.push_back(i+1);
}
for(int i=(m-1)%n;i<n;i=(i+m-1)%n){
cout<<v[i]<<" ";
v.erase(v.begin()+i);
n=v.size();
if(n==0){
break;
}
}
return 0;
}
6. 正误问题
#include <iostream>
#include <string>
#include <stack>
using namespace std;
string a;
stack<int> s; /* 操作符 */
stack<bool> v; /* 逻辑值 */
bool t,t1,t2;
void calculate() {
if(s.empty()) return;
if(s.top()==3) {
if(v.size()<1) {
printf("error\n");
exit(0);
}
t=v.top();
v.pop();
t=!t;
v.push(t);
} else if(s.top()==2) {
if(v.size()<2) {
printf("error\n");
exit(0);
}
t2=v.top();
v.pop();
t1=v.top();
v.pop();
t=(t1 && t2);
v.push(t);
} else if(s.top()==1) {
if(v.size()<2) {
printf("error\n");
exit(0);
}
t2=v.top();
v.pop();
t1=v.top();
v.pop();
t=(t1 || t2);
v.push(t);
}
s.pop();
}
int main(){
while(cin>>a){
if(a=="not") s.push(3);
else if(a=="and"){
if(v.empty()){
printf("error\n");
exit(0);
}
while(!s.empty()&&s.top()>=2) calculate();
s.push(2);
}else if(a=="or"){
if(v.empty()){
printf("error\n");
exit(0);
}
while(!s.empty()) calculate();
s.push(1);
}else if(a=="true") v.push(true);
else if(a=="false") v.push(false);
}
while(!s.empty()) calculate();
if(v.size()==1)
if(v.top()) printf("true\n");
else printf("false\n");
else printf("error\n");
return 0;
}
思维过程较为复杂,多次模拟即可
7. [NOIP2004 提高组] 合并果子 加强版
本人第一次60分的做法
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
ll a[maxn];
inline int read(){
char c=getchar();
int f=1;
int x=0;
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
return x*f;
}
int main(){
int n;
priority_queue<ll,vector<ll>, greater<ll>> pq;
n=read();
for(register int i = 0; i < n; i++){
a[i]=read();
pq.push(a[i]);
}
ll sum = 0;
while(true){
ll x = pq.top();
pq.pop();
ll y = pq.top();
pq.pop();
ll z = x + y;
sum = sum + z;
if(pq.empty())
break;
pq.push(z); /* 将z值导入pq中 */
}
printf("%lld\n",sum);
return 0;
}
桶排做法
#include <cstdio>
#include <queue>
#define int long long
using namespace std;
const int N = 1e7 + 5;
queue <int> q1;
queue <int> q2;
int time[N];
inline int read(){
char c=getchar();
int f=1;
int x=0;
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
return x*f;
}
signed main() {
int n;
n=read();
for (int i = 1; i <= n; ++i) {
int a;
a=read();
time[a]++;
}
for (int i = 1; i <= 1e7; ++i) {
while(time[i]) {
time[i] --;
q1.push(i);
/* 按从小到大的顺序插入 */
}
}
int ans = 0;
for (int i = 1; i < n; ++i) {
int x , y;
if((q1.front() < q2.front() && !q1.empty()) || q2.empty()) {
x = q1.front();
q1.pop();
}
else {
x = q2.front();
q2.pop();
}
if((q1.front() < q2.front() && !q1.empty()) || q2.empty()) {
y = q1.front();
q1.pop();
}
else {
y = q2.front();
q2.pop();
}
ans += x + y;
q2.push(x + y);
/* 合并后的放入其中 */
}
printf("%lld" , ans);
return 0;
}
该种做法减少插入排序次数,通过增大存储空间来满足时间限制
8. 序列合并
O ( n l o g 2 ( n ) ) O(nlog^2(n)) O(nlog2(n))
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define int long long
const int N=100005;
int a[N],b[N],ans[N];
int n;
priority_queue<int> p;
inline int read(){
char c=getchar();
int f=1;
int x=0;
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
return x*f;
}
signed main(){
n=read();
for(int i=0;i<n;i++){
a[i]=read();
}
for(int i=0;i<n;i++){
b[i]=read();
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
int x=a[i]+b[j];
if(p.size()<n){
p.push(x);
}
else{
if(p.top()>x){
p.pop();
p.push(x);
}
else{
break;
}
}
}
}
for(int i=n;i>=1;i--){
ans[i]=p.top();
p.pop();
}
for(int i=1;i<=n;i++){
printf("%d ",ans[i]);
}
return 0;
}