第五次作业题解
第五次作业题解
P3156 【深基15.例1】询问学号 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
\(vector\)的输入
-
for (auto &i : a) cin >> i;
-
for(int i = 0;i < n;i ++) cin >> a[i];
-
for(int i = 0;i < n;i ++){
cin >> x;
a.push_back(x);
}
前两种是\(vector\)大小确定的情况下才可以那样写,否则就要按照第三种写法
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n >> m;
vector<int> a(n);
for(auto &i : a) cin >> i;//也可以for(int i = 0;i < n;i ++) cin >> a[i];
while(m--){
int x;
cin >> x;
x--;
cout << a[x] << endl;
}
return 0;
}
[ABC088B] Card Game for Two - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int main() {
int n,m;
cin >> n;
int a = 0, b = 0;
vector<int> s(n);
for(int i = 0;i < n;i ++)
cin >> s[i];
sort(s.begin(), s.end(), greater<>());//从大到小排序
for(int i = 0;i < n;i += 2)//贪心思想,因为交叉取最大的数,所以最先选的人肯定选偶数下标
a += s[i];
for(int i = 1;i < n;i += 2)
b += s[i];
cout << a - b << endl;
return 0;
}
B3630 排队顺序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int main() {
int n,m;
cin >> n;
vector<int> a(n + 1);
for(int i = 1;i <= n;i ++){
cin >> m;
a[i] = m;
}
int k;
cin >> k;
while(k != 0){
cout << k << ' ';
k = a[k];//每次令k等于后面那个,链表思想
}
return 0;
}
B3631 单向链表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int main() {
int n,m;
vector<int> next(N);
cin >> n;
while(n--){
int op;
int x,y;
cin >> op >> x;
switch (op) {
case 1:
cin >> y;
next[y] = next[x];
next[x] = y;//链表插入,让x的下一个等于y,y的下一个等于x的下一个
break;
case 2:
cout << next[x] << endl;
break;
case 3:
next[x] = next[next[x]];//链表删除,x的下一个等于(x的下一个)的下一个,会有点绕
}
}
return 0;
}
B3765 [语言月赛202305] 超链接 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
bool vis[N];//标记哪些网页访问过
int main() {
int n,m;
cin >> n;
vector<int> g[n + 1];
for (int i = 1; i <= n; ++i) {
cin >> m;
int x;
while(m--){
cin >> x;
g[i].push_back(x);//g是个二维数组,它的列是不确定的,不能直接g[i][x];
}
}
int ans = 1;
vis[1] = 1;
for(auto i : g[1]){//只是点击两次,所以就去循环两次即可
if(!vis[i]){//如果没有访问过,就标记一下,答案+1
vis[i] = 1;
ans++;
}
for(auto j : g[i])
if(!vis[j]){
vis[j] = 1;//同上
ans++;
}
}
cout << ans << endl;
return 0;
}
B3614 【模板】栈 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;//这道题常数很大,不开无符号长整形即unsigned long long过不了
int main() {
ull n,m;
cin >> n;
while(n--){
cin >> m;
stack<ull> Q;
string s;
ull x;
while(m--){
cin >> s;
if(s == "push"){
cin >> x;
Q.push(x);
}else if(s == "size")
cout << Q.size() << endl;
else if(s == "pop"){
if(Q.empty())
cout << "Empty" << endl;
else
Q.pop();
}else if(s == "query"){
if(Q.empty())
cout << "Anguei!" << endl;
else
cout << Q.top() << endl;
}
}
}
return 0;
}
P1449 后缀表达式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
stack<int> Q;
for(int i = 0;i < s.size();i ++){
if(s[i] == '@') break;
int num = 0;
while(s[i] >= '0' && s[i] <= '9'){
num = num * 10 + (s[i] - '0');
i++;
}
if(s[i] == '.' || s[i] == '@') {
Q.push(num);
continue;
}
if(Q.size() > 1){
int m1 = Q.top();
Q.pop();
int m2 = Q.top();
Q.pop();
int ans;
switch (s[i]) {
case '-':
ans = m2 - m1;
break;
case '+':
ans = m2 + m1;
break;
case '*':
ans = m2 * m1;
break;
default:
ans = m2 / m1;
}
Q.push(ans);
}
}
cout << Q.top() << endl;
return 0;
}
P1241 括号序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
stack<int> Q;
bool v[110] = {0};
for(int i = 0;i < s.size();i ++){
if(Q.size()){//判断的时候Q.size()等价于!Q.empty()
if(s[i] == ')' && s[Q.top()] == '(' && Q.size()|| s[i] == ']' && s[Q.top()] == '[' && Q.size()) {
v[Q.top()] = v[i] = 1;
Q.pop();
}
}
if(s[i] == '(' || s[i] == '[')
Q.push(i);
}
for(int i = 0;i < s.size();i ++){
if(v[i])
cout << s[i];
else{
if(s[i] == '(' || s[i] == ')')
cout << "()";
else
cout << "[]";
}
}
return 0;
}
P1739 表达式括号匹配 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
bool v[1000];
int main() {
string s;
cin >> s;
stack<char> st;
for(auto i : s){
if(i == ')'){
if(st.empty()){
cout << "NO" << endl;
return 0;
}
else
st.pop();
}else if(i == '(')
st.push(i);
}
cout << (st.empty() ? "YES" : "NO") << endl;
return 0;
}
B3616 【模板】队列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n;
queue<int> Q;
while(n--){
int op ;
cin >> op;
switch (op) {
case 1:
int x;
cin >> x;
Q.push(x);
break;
case 2:
if(Q.empty())
cout << "ERR_CANNOT_POP" << endl;
else
Q.pop();
break;
case 3:
if(Q.empty())
cout << "ERR_CANNOT_QUERY" << endl;
else
cout << Q.front() << endl;
break;
default:
cout << Q.size() << endl;
}
}
return 0;
}
P1996 约瑟夫问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n >> m;
queue<int> Q;
for(int i = 1;i <= n;i ++){
Q.push(i);
}
int cnt = 0;
while(Q.size()){
int u = Q.front();
Q.pop();
cnt++;
if(cnt % m == 0){
cout << u << ' ';
}else
Q.push(u);//重新入队
}
return 0;
}
P1540 [NOIP2010 提高组] 机器翻译 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
bool v[1000];
int main() {
int n,m;
cin >> n >> m;
queue<int> Q;
int ans = 0;
for (int i = 1; i <= m; i++) {
int x;
cin >> x;
if (!v[x]) {
v[x] = 1;
if (Q.size() < n) {
ans++;
Q.push(x);
} else {
v[Q.front()] = 0;
Q.pop();
Q.push(x);
ans++;
}
}
}
cout << ans << endl;
return 0;
}
P3378 【模板】堆 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
priority_queue <int,vector<int>,greater<int>> Q;
cin >> n;
while(n--){
int op;
cin >> op;
if(op == 1){
cin >> m;
Q.push(m);
}else if(op == 2){
cout << Q.top() << endl;
}else
Q.pop();
}
return 0;
}
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将数放入一个从小到大的优先队列中,优先队列里会自动排序,每次取最少的果子合并即可
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int main() {
int n,m;
priority_queue<int,vector<int>,greater<int>> Q;
cin >> n;
for(int i = 0;i < n;i ++){
cin >> m;
Q.push(m);
}
int ans = 0;
while(Q.size() > 1){
int u = Q.top();
Q.pop();
int v = Q.top();
Q.pop();
ans += u + v;
Q.push(u + v);
}
cout << ans << endl;
return 0;
}
B2071 余数相同问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题挺多方法能做的,不过由于单独用set的题较少,所以就用这道题简单的写一下set的用法,set会自动去重与排序,所以当存进去三个数之后set的长度还是等于1的话说明三个都是一样的.
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int main() {
int n,m;
int a,b,c;
cin >> a >> b >> c;
m = min({a,b,c});
for(int i = 2;i <= m;i ++){
set<int> s;
s.insert(a % i),s.insert(b % i),s.insert(c % i);
if(s.size() == 1){
cout << i << endl;
break;
}
}
return 0;
}
P3613 【深基15.例2】寄包柜 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n >> m;
map<pair<int,int>,int> mp;//map的key和value可以存很多种类型,但是double不太行,因为double的值是一个不精确的数
while(m--){
int op,i,j;
cin >> op >> i >> j;
if(op == 1){
int x;
cin >> x;
mp[{i,j}] = x;
}else
cout << mp[{i,j}] << endl;
}
return 0;
}
P1097 [NOIP2007 提高组] 统计数字 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题你如果从1循环到1.5x\(10^9\)的话,无疑会超时,用for(auto [x,y] : mp)可以循环map里的值,x就代表了first,y代表second,如果你要for(auto i : mp)也是可以的,这时候i就是一个pair<int,int>类型的,你应当使用i.first和i.second
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n;
map<int,int> mp;
for(int i = 0 ;i < n;i ++){
cin >> m;
mp[m]++;
}
for(auto [x,y] : mp)
cout << x << ' ' << y << endl;
return 0;
}
P1305 新二叉树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
struct Node{
char root;
char left,right;
};
vector<Node> tree(128);
void traversal(char x){
if(x == '*') return;
cout << x;
traversal(tree[x].left);
traversal(tree[x].right);//这两个递归的执行顺序不同,最后输出的遍历结果也不同,这里是输出的前序遍历,想一想中序和后序遍历该怎样输出
};
int main() {
int n,m;
cin >> n;
char root;
for(int i = 1;i <= n;i ++){
char a,b,c;
cin >> a >> b >> c;
if(i == 1) root = a;
tree[a].left = b;
tree[a].right = c;
tree[b].root = tree[c].root = a;
}
traversal(root);
return 0;
}
P1827 [USACO3.4] 美国血统 American Heritage - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
若觉得还是不太理解可以看看这两篇博客
已知先序中序序列求后序序列(详细解释)已知先序中序求后序题目Elephant_King的博客-CSDN博客
二叉树遍历:已知前、中求后序;已知后、中求前序。_zadarmo_的博客-CSDN博客
这题和下一题基本是已知先序和中序求后序, 已知后序和中序求先序的模版,理解之后也可以背下来,很多时候用到直接把板子写上去就行,或者写篇博客下什么的
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
string s1,s2;
void traversal(int root,int start,int end){
/*
root 先序序列中当前递归层中根节点的下标
start 中序序列中子树的最左下标(子树开始的下标)
end 中序序列中子树的最右下标(子树结束的下标)
*/
if(start>end)
return ;
//递归结束的标志,因为子树的元素范围在下标[start,end]之内,当start>end的时候,说明以当前节点为空节点
int i=start;
//这里的i相当于只在中序遍历中有效,这里的i对于查找根节点root的先序序列完全没有意义,仅代表root在中序序列中的下标位置
while(i<end && s1[i]!=s2[root]) //寻找root在中序序列中的位置
i++;
traversal(root + 1, start, i - 1);//递归左子树
traversal(root + 1 - start + i, i + 1, end);//递归右子树
cout << s1[i];
};
int main() {
cin >> s1 >> s2;
traversal(0,0,s2.size() - 1);
return 0;
}
P1030 [NOIP2001 普及组] 求先序排列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
string s1,s2;
void traversal(int root,int start,int end){
if(start>end)
return ;
int i=start;
while(i<end && s1[i]!=s2[root])
i++;
cout << s1[i];
traversal(root - end + i - 1, start, i - 1);
traversal(root - 1, i + 1, end);
};
int main() {
cin >> s1 >> s2;
traversal(s2.size() - 1,0,s2.size() - 1);
return 0;
}