intmain(){ // 基于流的 I/O 优化 // std::cin.tie(nullptr); // 解除关联 // std::ios::sync_with_stdio(false); // 关闭同步 ll n,m; // n: 区域数;m: 操作数 cin >> n >> m; vector<list<ll>> listt(n); // 存储各区域的军事信息 for (ll i = 0; i < n; i++) { ll t; cin >> t; // t: 军队个数 for (ll j = 0; j < t; j++) { ll temp; cin >> temp; // temp: 各军队人数 listt[i].push_back(temp); } } for (ll i = 0; i < m; i++) { char type; cin >> type; if (type == 'U') { ll a,b; cin >> a >> b; a--; b--; // 编号从 1 到 N,减 1 和数组下标对齐 listt[a].splice(listt[a].end(), listt[b]); // splice(a, b) 将 b 的内容转移到 this*,位置为 a } elseif (type == 'I') { ll a,x; cin >> a >> x; a--; listt[a].push_front(x); // list 的向前插入 } elseif (type == 'D') { ll a,x; cin >> a >> x; a--; listt[a].remove(x); // remove() 移除符合特定条件的元素 } elseif (type == 'Q') { ll y; cin >> y; y--; if (listt[y].empty()) { cout << "-1\n"; } else { bool first = true; for (auto j : listt[y]) { if (!first) cout << " "; cout << j; first = false; } cout << "\n"; } } } return0; }
洗盘子
★实验任务
猪妈妈有很多小猪仔,每次吃完饭洗盘子是一个很大的问题。这天猪妈妈想出了一个方法。她让小猪们排成一队,从 2 开始给他们编号。每次排在最前面的不用洗盘子(假设它的编号是 i ),但是,排在它后面的第 i 只 ,2 i 只,3 i 只… 的小猪要洗盘子。让排在最前面以及要洗盘子的小猪出队,然后重复上述过程。那些不用洗盘子的小猪被称为幸运猪(lucky pigs),把它们的编号从小到大排序,现在要问第 n 个幸运猪的编号是多少。
constint N = 1e5 + 10; int a[N], b[N], c[N], vis[N];
voidsolve() { int n, m; cin >> n >> m; int idx = 0; for(int i=1;i<=n;i++){ int x; cin >> x; if(x==0){ vis[i] = 1; // 标记序列 a 中缺失元素的位置 } else { a[++idx] = x; // 收集 a 中非 0 的数 } } for(int i = 1; i <= m; i++) { cin >> b[i]; } // 允许任意交换意味着原始位置已经不重要了,只剩下“数的集合”重要 // 问题变成:能否把“a 的非零数和 b 中的数”重新排列,按原位置规则放回(形成新序列),使整个序列严格递增? sort(a + 1, a + idx + 1); // std::sort(container.begin(), container.end()); sort(b + 1, b + m + 1); int idx1 = 0, idx2 = 0; for(int i=1;i<=n;i++){ if(vis[i]){ c[i] = b[++idx1]; // 如果此位置是 a 中缺失的元素位置,那么用序列 b 填充 } else { c[i] = a[++idx2]; // 如果没缺失,则用 a 中原本没缺失的元素填充 } if(i > 1){ // 发现填充违规,说明当前最小可用的数都不够大,而换用更大的数会把这个较小数留给后面更大的数,更难实现递增 if(c[i] <= c[i - 1]){ cout << "-1" << "\n"; return; } } } for(int i=1;i<=n;i++){ if(i != 1){ cout << " "; } cout << c[i]; } cout << "\n"; }
intmain() { solve(); }
树
文件管理器
好难 QAQ
背景
操作系统具有对计算机硬件资源管理和调度的功能。文件是对占用了硬盘一定空间的对象的描述和抽象。考虑一般的文件具有文件名、大小和创建时间。文件管理在任何操作系统中都是必不可少的。文件管理器是用户用来观察和操作文件的一个软件。考虑一个简易的文件管理器,用户可以通过这个简易的文件管理器对某个目录下文件最大/小、文件名 (字符串) 字典序最大/最小的一些文件,即按 XX 排序功能,此外文件管理器具有删除和添加文件的功能。输入保证目录只有一级,操作随机。
输入及输出格式
第 1 行输入一个 Q (1<=Q<=100000),表示操作的次数。
第 2 - Q + 1 行输入一行操作序列
操作序列的格式为 op args
当 op = 1, 即第一种操作时,args 的格式为 folder name size,表示将要在某个 folder 目录 (1<=folder<=5 的整数) 下添加文件名为 name (1<=name<=100000 的整数) 的文件,文件大小为 size (1<=size<=100000 的整数),如果文件名重复,就先删除原来的文件再进行 1 操作;
当 op = 2, 即第二种操作时,args 的格式为 folder name,表示将要在某个 folder 目录 (1<=folder<=5 的整数) 下删除文件名为 name (1<=name<=100000 的整数) 的文件,如果文件名不存在,操作不执行;
当 op = 3, 即第三种操作时,args 的格式为 folder k,表示输出某个目录下文件大小最大至第 k 大的文件名,如果大小相同按文件名数字从小到大输出,如果不满 k 个文件只需要输出已有的文件名,如果文件夹为空或不存在则输出一个空行;
当 op = 4, 即第四种操作时,args 的格式为 folder k,表示输出某个目录下文件名数字大小最小至第 k 小的文件名,如果不满 k 个文件只需要输出已有的文件名,如果文件夹为空或不存在则输出一个空行;
#include<iostream> usingnamespace std; constint MAX = 10000; int a[MAX], n; voiddfs(int * a, int begin, int end){ bool l = 1; bool r = 1; cout << a[end]; // 后序遍历的最后一个一定是根 int i = begin;
// [ begin ... i-1 ] < root → 左子树 // [ i ... end-1 ] > root → 右子树 while (i < end && a[i]<a[end]) { i++; } if (i==begin) { l=0; } if (i==end) { r=0; } if (l) { cout << "<"; dfs(a, begin, i - 1); cout << ">"; } if (r) { cout << "<"; dfs(a, i, end - 1); cout << ">"; } } intmain(){ cin >> n; for (int i=1; i<=n; i++){ cin>>a[i]; } dfs(a, 1, n); return0; }
散列表
Sins of a Solar Empire P7
★实验任务
正如你所知道 sins 是一个贪玩的不得了的小 P 孩(如果你非常讨厌他可以直接跳到第二段),你也知道他最近很喜欢玩一个叫做太阳帝国的原罪的策略游戏我向你保证这是太阳帝国原罪系列的第七章了。
现在 sins 拥护 N 个星球,每个星球 m 种不同的资源,每个资源都拥有一个编号 A,对于 sins 来说 N 个星球都有的资源才是最宝贵的,他想知道这样的资源有哪些?
★数据输入
第 1 行是正整数 N(1<=N<=1000)。
第 2~N + 1 行各有一个正整数 m 和 m 个正整数编号 A (有重复),(0 < m<=1000, 0 <= A <=10^9).
★数据输出
第一行一个整数 S,表示 N 个星球都拥有的资源个数。
如果 S 不等于 0 输出第二行,按照升序输出 S 个整数表示资源编号 (无重复),资源编号之间有空格,结尾没有空格。
#include<iostream> #include<unordered_map> #include<unordered_set> #include<vector> #include<algorithm> usingnamespace std; intmain(){ int N; cin >> N; unordered_map<int, int> Count; for (int i = 0; i < N; ++i) { int m; cin >> m; unordered_set<int> only; for (int j = 0; j < m; ++j) { int A; cin >> A; only.insert(A); } for (int res : only) { Count[res]++; } } vector<int> common; for (constauto& pair : Count) { if (pair.second == N) { common.push_back(pair.first); } } sort(common.begin(), common.end()); cout << common.size() << endl; if (!common.empty()) { for (int i = 0; i < common.size(); ++i) { if (i > 0) { cout << " "; } cout << common[i]; } cout << endl; } return0; }
特殊匹配 R
★实验任务
定义一种语言 L,L 语言中所有的字符串只能由 abc 三个字母组成。
在语言 L 之上定义一种特殊匹配规则 R,R 的定义如下:假设有两个字符串 x 和 y,x 和 y 等长,且 x 与 y 有且只有一个位置上的字符不同。
例如字符串 x 为 “abc”:
(1)若字符串 y 为” abb”,这 x 与 y 符合 R 匹配;
(2)若 y 为” abc” 或” bbb” 或” abcc”,则 x 与 y 不符合 R 匹配。
现给定一个由 n 个 x 字符串构成的匹配表 r,然后进行 m 次询问。每次询问输入一个 y 字符串,然后判断 r 表中是否存在与 y 符合 R 匹配的 x 字符串,若有输出” YES”,否则输出” NO”。
★数据输入
输入中第一行给出一整数 n,m(1<=n,m<=1000)。
接下来 n 行给出 n 个 x 字符串。
接下来 m 行,每行输入一个 y 字符串进行询问。
题目保证每一个字符串的长度在 1000 以内。
★数据输出
对于 m 个询问,每个询问输出在 x 个字符串中是否有与 y 字符串符合 R 匹配的字符串,若有输出” YES”,否则输出” NO”。
intmain(){ int n, m; cin >> n >> m; unordered_set<string> x_set; vector<string> x_list; for (int i = 0; i < n; i++) { string x; cin >> x; x_set.insert(x); x_list.push_back(x); } for (int i = 0; i < m; i++) { string y; cin >> y; int len = y.length(); bool found = false; for (const string& x : x_list) { if (x.length() != len) continue; int diff_count = 0; for (int j = 0; j < len; j++) { if (x[j] != y[j]) { diff_count++; if (diff_count > 1) break; } } if (diff_count == 1) { found = true; break; } } cout << (found ? "YES" : "NO") << endl; } return0; }
intmain() { int n; cin>>n; int a[100]; for (int i=0;i<n;i++) { cin>>a[i]; } int len=n; int total=0; while(len>1) { int min1=0,min2=1; if (a[min1]>a[min2]) swap(min1,min2); for (int i=2;i<len;i++) { if (a[i]<a[min1]) { min2=min1; min1=i; } elseif(a[i]<a[min2]) { min2=i; } } int sum=a[min1]+a[min2]; total+=sum; a[min1]=sum; a[min2]=a[len-1]; len--; } cout<<total<<endl; return0; }
int N, M, S, T; vector<pair<int, int>> graph[MAXN]; int dist[MAXN]; bool visited[MAXN]; vector<int> dag[MAXN];
voiddijkstra(int start){ memset(dist, 0x3f, sizeof(dist)); memset(visited, false, sizeof(visited)); dist[start] = 0; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; pq.push({0, start}); while (!pq.empty()) { int d = pq.top().first; int u = pq.top().second; pq.pop(); if (visited[u]) continue; visited[u] = true; for (auto &e : graph[u]) { int v = e.first; int w = e.second; if (dist[v] > d + w) { dist[v] = d + w; pq.push({dist[v], v}); } } } }
intmain(){ cin >> N >> M; for (int i = 0; i < M; i++) { int u, v, len; cin >> u >> v >> len; graph[u].push_back({v, len}); graph[v].push_back({u, len}); } cin >> S >> T;
// 构建DAG:只包含从距离大的点指向距离小的点的边 for (int u = 1; u <= N; u++) { for (auto &e : graph[u]) { int v = e.first; // 只添加满足条件的边:dist[u] > dist[v] if (dist[u] > dist[v]) { dag[u].push_back(v); } } }
// 按到T的距离升序排序所有顶点(距离小的先处理) vector<int> nodes; for (int i = 1; i <= N; i++) { if (dist[i] < INF) { nodes.push_back(i); } } sort(nodes.begin(), nodes.end(), [](int a, int b) { return dist[a] < dist[b]; });
// 动态规划计算路径条数 vector<ll> dp(N + 1, 0); dp[T] = 1; for (int v : nodes) { if (v == T) continue; for (int u : dag[v]) { dp[v] += dp[u]; } }
// 输出路径条数 cout << dp[S] << endl;
return0; }
最小生成树
★问题描述
给定平面上的 n 个点,添加一些边使得任何两个点之间都能相互到达,求添加的边的长度总和最小为多少
★数据输入
第一行一个正整数 n (1<=n<=5000),表示序列有 n 个点,
接下来有 n 行,每行两个整数 xi 和 yi,(-1000000≤xi,yi≤1000000),表示 n 个点的坐标