【刷题日记】简单的STL练习题

眼红的Medusa(洛谷P1571)

题目描述

虽然 Miss Medusa 到了北京,领了科技创新奖,但是她还是觉得不满意。原因是:他发现很多人都和她一样获了科技创新奖,特别是其中的某些人,还获得了另一个奖项——特殊贡献奖。而越多的人获得了两个奖项,Miss Medusa就会越眼红。于是她决定统计有哪些人获得了两个奖项,来知道自己有多眼红。

输入格式

第一行两个整数 \(n, m\),表示有 \(n\) 个人获得科技创新奖,\(m\) 个人获得特殊贡献奖。

第二行 \(n\) 个正整数,表示获得科技创新奖的人的编号。

第三行 \(m\) 个正整数,表示获得特殊贡献奖的人的编号。

输出格式

输出一行,为获得两个奖项的人的编号,按在科技创新奖获奖名单中的先后次序输出。

样例 #1

样例输入 #1

4 3
2 15 6 8
8 9 2

样例输出 #1

2 8

提示

对于 \(60\%\) 的数据,\(0 \leq n, m \leq 1000\),获得奖项的人的编号 \(\lt 2 \times 10^9\)

对于 \(100\%\) 的数据,\(0 \leq n, m \leq 10^5\),获得奖项的人的编号 \(\lt 2 \times 10^9\)

输入数据保证第二行任意两个数不同,第三行任意两个数不同。

题解

为了实现去重功能,可以使用map或set。既然输出要按照科技创新奖的获奖名单来,那就为其创造一个队列,先进先出即可。

AC代码
#include <bits/stdc++.h>
using namespace std;

map<long long,bool>mp;
queue<long long>que;
long long scan,n,m;

int main(){
	scanf("%lld %lld",&n,&m);
	
	for(long long i = 0;i<n;i++){
		scanf("%lld",&scan);
		que.push(scan);
	}
	
	for(long long i = 0;i<m;i++){
		scanf("%lld",&scan);
		mp[scan] = 1;
	}
	
	while(!que.empty()){
		if(mp[que.front()])	printf("%lld ",que.front());
		que.pop();
	}
	
	return 0;
}

小王子单链表(蓝桥1110)

题目

题目链接

题解

AC代码
#include <bits/stdc++.h>
using namespace std;

list<int>a{1,2,3,4,5,6,7,8,9,10};
int m,x,num;

int main(){
	scanf("%d",&m);
	
	while(m--){
		scanf("%d",&x);
		a.remove(x);
		a.push_front(x);
		for(auto i:a)	printf("%d ",i);
		printf("\n");
	}
	
	return 0;
}

整数删除(蓝桥3515)

题目

题目链接

题解

用数组做只能通过20%,用双向链表只能通过30%,正确做法是结合双向链表与优先队列,同时处理数据。

30%通过代码
#include <bits/stdc++.h>
using namespace std;

list<int>a;
long long n,k,scan,num;

int main(){
    scanf("%lld %lld",&n,&k);
    
    for(long long i = 0;i<n;i++){
        scanf("%lld",&scan);
        a.push_back(scan);
    }
    
    while(k--){
        auto min_it = min_element(a.begin(),a.end());
        num = *min_it;
        if(min_it != a.begin()){
            min_it --;
            *min_it += num;
            min_it ++;
        }
        min_it ++;
        if(min_it != a.end()){
            *min_it += num;
        }
        min_it --;
        a.erase(min_it);
    }
    
    for(auto it:a)    printf("%lld ",it);
    return 0;
}
AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;

long long v[N],L[N],R[N],n,k,t;	//用L、R两个数组实现双向链表

void del(long long x) {	//删除元素
	R[L[x]] = R[x];
	L[R[x]] = L[x];
	v[L[x]] += v[x];
	v[R[x]] += v[x];
	return;
}

priority_queue<pair<long long, long long>, vector<pair<long long, long long>>, greater<pair<long long, long long>>>Q;
//小根堆优先队列

int main(){
	scanf("%lld %lld",&n,&k);
	
	//构造双向链表
	R[0] = 1;
	L[n+1] = n;
	for(long long i = 1;i<=n;i++){
		cin >> v[i];
		L[i] = i - 1;
		R[i] = i + 1;
		Q.push({v[i], i});
	}
	
	//重复模拟操作
	while(k--){
		auto p = Q.top();
		Q.pop();
		if(p.first != v[p.second]){	//该队头已经被del,需要撤销操作
			Q.push({v[p.second],p.second});
			k++;
		}
		else del(p.second);
	}
	
	t = R[0];	//R[0]指向第一个数
	while(t != n + 1){
		printf("%lld ",v[t]);
		t = R[t];
	}
	
	return 0;
}

约瑟夫问题(洛谷P1996)

题目描述

\(n\) 个人围成一圈,从第一个人开始报数,数到 \(m\) 的人出列,再由下一个人重新从 \(1\) 开始报数,数到 \(m\) 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

注意:本题和《深入浅出-基础篇》上例题的表述稍有不同。书上表述是给出淘汰 \(n-1\) 名小朋友,而该题是全部出圈。

输入格式

输入两个整数 \(n,m\)

输出格式

输出一行 \(n\) 个整数,按顺序输出每个出圈人的编号。

样例 #1

样例输入 #1

10 3

样例输出 #1

3 6 9 2 7 1 8 5 10 4

提示

\(1 \le m, n \le 100\)

题解

直接用队列即可。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

long long n,m,now = 0;
queue<int>q;

int main(){
	scanf("%lld %lld",&n,&m);
	for(long long i = 0;i<n;i++)	q.push(i+1);
	while(!q.empty()){
		if(now != m-1){
			now++;
			q.push(q.front());
		}
		else{
			now = 0;
			printf("%lld ",q.front());
		}
		q.pop();
	}
	return 0;
}

餐厅排队(蓝桥3745)

题目

题目链接

题解

双端队列,直接模拟。

AC代码
#include <bits/stdc++.h>
using namespace std;

queue<int>que;
int command,x,q;

int main(){
	scanf("%d",&q);
	while(q--){
		scanf("%d",&command);
		switch(command){
			case 1:
				scanf("%d",&x);
				que.push(x);
				break;
			case 2:
				que.pop();
				break;
			case 3:
				printf("%d %d\n",que.front(),que.back());
				break;
		}
	}
	return 0;
}

小桥的神秘礼物盒(蓝桥3746)

题目

题目链接

题解

跟上一题不能说一模一样吧。。只能说完全相同。。

AC代码
#include <bits/stdc++.h>
using namespace std;

long long n,command,x;
queue<long long>q;

int main(){
	scanf("%lld",&n);
	while(n--){
		scanf("%lld",&command);
		switch(command){
			case 1:
				scanf("%lld",&x);
				q.push(x);
				break;
			case 2:
				if(q.empty())
					printf("lan\n");
				else
					q.pop();
				break;
			case 3:
				if(q.empty())
					printf("qiao\n");
				else
					printf("%lld\n",q.front());
				break;
			case 4:
				printf("%lld\n",q.size());
				break;
		}
	}
	return 0;
}

小蓝的神奇复印机(蓝桥3749)

题目

题目链接

题解

为了保证被删除的目标是重要程度最大的,可以同步地用一个优先队列去维护数据。

AC代码
#include <bits/stdc++.h>
using namespace std;

long long n,x,scan,ans = 0;
queue<pair<long long,bool>>q;
priority_queue<long long>pq;

int main(){
	scanf("%lld %lld",&n,&x);
	for(long long i = 0;i<n;i++){
		scanf("%lld",&scan);
		q.push({scan,i==x});
		pq.push(scan);
	}
	//模拟任务
	while(1){
		if(q.front().first == pq.top()){	//确定是最重要的打印任务
			ans ++;
			pq.pop();
			if(q.front().second){
				printf("%lld",ans);
				break;
			}
			q.pop();
		}
		else{
			auto s = q.front();
			q.pop();
			q.push(s);
		}
	}
	return 0;
}
posted @ 2025-01-23 19:58  Alkaid16  阅读(54)  评论(0)    收藏  举报