天梯赛L2练习集
- L2-001 紧急救援
- L2-002 链表去重
- L2-003 月饼
- L2-004 这是二叉搜索树吗?
- L2-005 集合相似度
- L2-006 树的遍历
- L2-007 家庭房产
- L2-008 最长对称子串
- L2-009 抢红包
- L2-010 排座位
- L2-011 玩转二叉树
- L2-012 关于堆的判断
- L2-013 红色警报
- L2-014 列车调度
- L2-015 互评成绩
- L2-016 愿天下有情人都是失散多年的兄妹
- L2-017 人以群分
- L2-018 多项式A除以B
- L2-019 悄悄关注
- L2-020 功夫传人
- L2-021 点赞狂魔
- L2-022 重排链表
- L2-023 图着色问题
- L2-024 部落
- L2-025 分而治之
- L2-026 小字辈
- L2-027 名人堂与代金券
- L2-028 秀恩爱分得快
- L2-029 特立独行的幸福
- L2-030 冰岛人
- L2-031 深入虎穴
- L2-032 彩虹瓶
- L2-033 简单计算器
- L2-034 口罩发放
- L2-035 完全二叉树的层序遍历
- L2-036 网红点打卡攻略
- L2-037 包装机
- L2-038 病毒溯源
- L2-039 清点代码库
- L2-040 哲哲打游戏
- L2-041 插松枝
- L2-042 老板的作息表
- L2-043 龙龙送外卖
- L2-044 大众情人
- L2-045 堆宝塔
- L2-046 天梯赛的赛场安排
- L2-047 锦标赛
- L2-048 寻宝图
- L2-049 鱼与熊掌
- L2-050 懂蛇语
- L2-051 满树的遍历
- L2-052 吉利矩阵
L2-001 紧急救援
朴素dijkstra
求最短路及对应路径,最短路长度最短即时间最短,时间相同的情况下召集的人最多
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 510;
int g[N][N];
bool st[N];
// 结点人数 最短路径长度 召集最多人 路径条数 结点的pre
int w[N], d[N], va[N], cnt[N], path[N];
int n, m, s, D;
void dijkstra()
{
memset(d, 0x3f, sizeof d);
d[s] = 0;
for(int i = 0; i < n; i ++)va[i] = w[i];
cnt[s] = 1;
for(int k = 0; k < n - 1; k ++)
{
int t = -1;
for(int i = 0; i < n; i ++)
if(!st[i] && (t == -1 || d[t] > d[i]))t = i;
st[t] = true;
for(int i = 0; i < n; i ++)
{
if(d[i] > d[t] + g[t][i])
{
d[i] = d[t] + g[t][i];
cnt[i] = cnt[t];
va[i] = va[t] + w[i];
path[i] = t;
}
else if(d[i] == d[t] + g[t][i])
{
cnt[i] += cnt[t];
if(va[i] < va[t] + w[i])
{
va[i] = va[t] + w[i];
path[i] = t;
}
}
}
}
}
int main()
{
cin>>n>>m>>s>>D;
for(int i = 0; i < n; i ++)
{
cin>>w[i];
}
memset(g, 0x3f, sizeof g);
while(m --)
{
int a, b, c;cin>>a>>b>>c;
g[a][b] = g[b][a] = c;
}
dijkstra();
cout<<cnt[D]<<' '<<va[D]<<endl;
vector<int>v;
int id = D;
while(id != s)
{
v.push_back(id);
id = path[id];
}
cout<<s;
for(int i = v.size() - 1; i >= 0; i --)cout<<' '<<v[i];
return 0;
}
L2-002 链表去重
小模拟
先把原链表构建起来,用两个数组即可,一个指针指向指针的,另一个指针指向值的
然后从前往后遍历判重,构建两个新链表
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int ne[N];
int e[N];
bool st[N];
int main()
{
int s, n;cin>>s>>n;
while(n --)
{
int a, b, c;cin>>a>>b>>c;
ne[a] = c;
e[a] = b;
}
vector<int> list1, list2;
while(s != -1)
{
int j = e[s];
if(st[abs(j)])list2.push_back(s);
else list1.push_back(s);
st[abs(j)] = true;
s = ne[s];
}
for(int i = 0; i < list1.size(); i ++)
{
if(i == list1.size() - 1)
printf("%05d %d %d\n", list1[i], e[list1[i]], -1);
else printf("%05d %d %05d\n", list1[i], e[list1[i]], list1[i + 1]);
}
for(int i = 0; i < list2.size(); i ++)
{
if(i == list2.size() - 1)
printf("%05d %d %d", list2[i], e[list2[i]], -1);
else printf("%05d %d %05d\n", list2[i], e[list2[i]], list2[i + 1]);
}
return 0;
}
L2-003 月饼
结构体排序
按照价值从大到小排序,然后从前往后一个一个用直到用光需求量
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
struct node
{
double num, sum;
double val;
bool operator < (const node &W )
{
return val > W.val;
}
}nd[N];
int main()
{
int n;
double m;cin>>n>>m;
for(int i = 0; i < n; i ++)
cin>>nd[i].num;
for(int i = 0; i < n; i ++)
{
double sum;cin>>sum;
nd[i].sum = sum;
nd[i].val = 1.0 * sum / nd[i].num;
}
sort(nd, nd + n);
double ans = 0;
for(int i = 0; i < n; i ++)
{
double num = nd[i].num;
double val = nd[i].val;
if(m > num)ans += nd[i].sum, m -= num;
else
{
ans += val * m;
break;
}
}
printf("%.2f", ans);
return 0;
}
L2-004 这是二叉搜索树吗?
数据结构
先判断是否二叉搜索树,再判断是否镜像
有个坑点就是这个输出树说的是
如果输入序列是对一棵二叉搜索树或其镜像进行前序遍历的结果,则首先在一行中输出
YES,然后在下一行输出该树后序遍历的结果。
明显就有歧义,如果是镜像,那我输出镜像还是二叉搜索树?
#include <iostream>
#include <vector>
using namespace std;
int a[1010];
vector<int>v;
bool flag = false;
void find(int l, int r)
{
if(l > r)return ;
if(l == r)
{
v.push_back(a[l]);
return ;
}
int i = l + 1, j = r;
if(flag)
{
while(i <= r && a[i] < a[l])i++;
while(j > l && a[j] >= a[l])j --;
}
else
{
while(i <= r && a[i] >= a[l])i ++;
while(j > l && a[j] < a[l])j --;
}
if(i != j + 1)return ;
find(l + 1, j), find(i, r);
v.push_back(a[l]);
}
int main()
{
int n;cin>>n;
for(int i = 0; i < n; i ++)cin>>a[i];
find(0, n - 1);
if(v.size() == n)
{
cout<<"YES"<<endl;
for(int i = 0; i < n; i ++)
{
if(i)cout<<' ';
cout<<v[i];
}
}
else
{
v.clear();
flag = true;
find(0, n - 1);
if(v.size() == n)
{
cout<<"YES"<<endl;
for(int i = 0; i < n; i ++)
{
if(i)cout<<' ';
cout<<v[i];
}
}
else cout<<"NO";
}
return 0;
}
L2-005 集合相似度
STL库 的set
#include<iostream>
#include <set>
using namespace std;
set<int> s[55];
int main()
{
int n;cin>>n;
for(int i = 1; i <= n; i ++)
{
int m;cin>>m;
while(m --)
{
int x;cin>>x;
s[i].insert(x);
}
}
int m;cin>>m;
while(m --)
{
int a, b;cin>>a>>b;
int cnt = 0;
for(auto i : s[a])
if(s[b].count(i))cnt ++;
int sum = s[a].size() + s[b].size() - cnt;
printf("%.2f%%\n", 100.0 * cnt / sum);
}
return 0;
}
L2-006 树的遍历
数据结构
递归遍历将结点放到一个数组里然后输出
#include <iostream>
#include <map>
using namespace std;
int h[31], m[31];
map<int, int> mp;
void dfs(int hl, int hr, int ml, int mr, int idx)
{
if(hl > hr || ml > mr)return ;
mp[idx] = h[hr];// 根
int id = ml;
while(m[id] != h[hr])id ++; // 找根在中序的位置
dfs(hl, hl + id - 1 - ml, ml, id - 1, idx * 2);
dfs(hl + id - ml, hr - 1, id + 1, mr, idx * 2 + 1);
}
int main()
{
int n;cin>>n;
for(int i = 0; i < n; i ++)cin>>h[i];
for(int i = 0; i < n; i ++)cin>>m[i];
dfs(0, n - 1, 0, n - 1, 1);
for(auto i = mp.begin(); i != mp.end(); i ++)
{
if(i != mp.begin())cout<<' ';
cout<<i -> second;
}
return 0;
}
L2-007 家庭房产
并查集 自定义排序
先统计一个个家族的信息,根节点给最小的编号,记录每个家族的总人数和房子总面积,排序
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int p[N], peo[N];
double cnt[N], area[N];
int ide[N];
int find(int x)
{
if(p[x] != x)p[x] = find(p[x]);
return p[x];
}
int main()
{
for(int i = 0; i < N; i ++)p[i] = i, peo[i] = 1;//0结点占那么多分草泥马
int n;cin>>n;
for(int i = 0; i < n; i ++)
{
int id;cin>>id;ide[i] = id;
int k = 2;
while(k --)
{
int x;cin>>x;
if(x != -1)
{
int a = find(id), b = find(x);
if(a == b)continue;
if(a < b)swap(a, b);
p[a] = b;
peo[b] += peo[a];
}
}
cin>>k;
while(k --)
{
int x;cin>>x;
if(x != -1)
{
int a = find(id), b = find(x);
if(a == b)continue;
if(a < b)swap(a, b);
p[a] = b;
peo[b] += peo[a];
}
}
cin>>cnt[id]>>area[id];
}
set<int> s;
for(int i = 0; i < n; i ++)
{
int id = ide[i];
int fa = find(id);
s.insert(fa);
if(id != fa)
{
cnt[fa] += cnt[id];
area[fa] += area[id];
}
}
n = s.size();
cout<<n<<endl;
vector<int> v;
for(auto i : s)
{
v.push_back(i);
cnt[i] = 1.0*cnt[i] / peo[i];
area[i] = 1.0*area[i] / peo[i];
}
sort(v.begin(), v.end(), [&](int a, int b){
if(area[a] != area[b])return area[a] > area[b];
return a < b;
});
for(auto i : v)
printf("%04d %d %.3f %.3f\n", i, peo[i], cnt[i], area[i]);
return 0;
}
L2-008 最长对称子串
暴力枚举
遍历所有情况,以一个字符或两个字符为中心进行扩展,就是分奇偶串
#include <iostream>
using namespace std;
int main()
{
string s;getline(cin, s);
int n = s.size();
int res = 0;
for(int i = 0; i < n; i ++)
{
int l = i - 1, r = i + 1;
int t = 1;
while(l >= 0 && r < n && s[l] == s[r])t += 2, l --, r ++;
res = max(res, t);
l = i, r = i + 1;
t = 0;
while(l >= 0 && r < n && s[l] == s[r])t += 2, l --, r ++;
res = max(res, t);
}
cout<<res;
return 0;
}
L2-009 抢红包
自定义排序
记录交易流水:发的人扣钱,收的人加钱,加红包次数。
对1-n的排列按照钱大小、红包个数和编号优先级排序
#include <iostream>
using namespace std;
const int N = 1e4 + 10;
int p[N], cnt[N];
double m[N];
int main()
{
int n;cin>>n;
for(int i = 1; i <= n; i ++)p[i] = i;
for(int i = 1; i <= n; i ++)
{
int k;cin>>k;
while(k --)
{
int x;
double y;cin>>x>>y;
m[i] -= y;
m[x] += y;
cnt[x] ++;
}
}
sort(p + 1, p + 1 + n, [&](int a, int b){
if(m[a] != m[b])return m[a] > m[b];
else if(cnt[a] != cnt[b])return cnt[a] > cnt[b];
else return a < b;
});
for(int i = 1; i <= n; i ++)
{
int id = p[i];
printf("%d %.2f\n", id, m[id] / 100);
}
return 0;
}
L2-010 排座位
并查集
敌人与敌人、敌人与朋友之间没什么必要关系,但是朋友的朋友就是朋友,那就将朋友与朋友组成朋友圈,敌人与敌人单独记录
#include <iostream>
using namespace std;
bool g[110][110];
int p[110];
int find(int x)
{
if(p[x] != x)p[x] = find(p[x]);
return p[x];
}
int main()
{
int n, m, k;cin>>n>>m>>k;
for(int i = 1; i <= n; i ++)p[i] = i;
while(m --)
{
int a, b, c;cin>>a>>b>>c;
if(c == 1)p[find(a)] = find(b);
else g[a][b] = g[b][a] = true;
}
while(k --)
{
int a, b;cin>>a>>b;
int pa = find(a), pb = find(b);
if(pa == pb && !g[a][b])puts("No problem");
else if(pa != pb && !g[a][b])puts("OK");
else if(pa == pb && g[a][b])puts("OK but...");
else puts("No way");
}
return 0;
}
L2-011 玩转二叉树
数据结构
#include <bits/stdc++.h>
using namespace std;
int m[33], q[33];
map<int, int> mp;
void dfs(int ql, int qr, int ml, int mr, int idx)
{
if(ql > qr || ml > mr)return ;
mp[idx] = q[ql];
int l = ml;
while(m[l] != q[ql])l ++;// 找中序的根
//先右再左就是镜面反转
dfs(ql + 1, ql + 1 + l - ml - 1, ml, l - 1, idx * 2 + 1);
dfs(ql + 1 + l - ml, qr, l + 1, mr, idx * 2);
}
int main()
{
int n;cin>>n;
for(int i = 1; i <= n; i ++)cin>>m[i];
for(int i = 1; i <= n; i ++)cin>>q[i];
dfs(1, n, 1, n, 1);
for(auto i = mp.begin(); i != mp.end(); i ++)
{
if(i != mp.begin())cout<<' ';
cout<<i -> second;
}
return 0;
}
L2-012 关于堆的判断
数据结构
手动建小根堆堆
#include <iostream>
using namespace std;
const int N = 1010;
int h[N];
int n, m;
void up(int u)
{
if(u > 1 && h[u] < h[u / 2])
{
swap(h[u], h[u / 2]);
up(u / 2);
}
}
int find(int u,int x)
{
if(u>n || h[u]>x)return -1;
if(h[u]==x)return u;
return max(find(u*2,x),find(u*2+1,x));
}
int main()
{
cin>>n>>m;
for(int i = 1; i <= n; i ++)
{
cin>>h[i];
up(i);
}
while(m --)
{
int a;cin>>a;
int u1 = find(1, a);
string s;cin>>s;
if(s == "is")
{
cin>>s;
if(s == "the")
{
cin>>s;
if(s == "root")
{
if(h[1] == a)puts("T");
else puts("F");
}
else
{
cin>>s;
int b;cin>>b;
int u2 = find(1, b);
if(u1 == u2 / 2)puts("T");
else puts("F");
}
}
else
{
cin>>s>>s;
int b;cin>>b;
int u2 = find(1, b);
if(u1 / 2 == u2)puts("T");
else puts("F");
}
}
else
{
int b;cin>>b;
cin>>s>>s;
int u2 = find(1, b);
if(abs(u1 - u2) == 1 && u1 / 2 == u2 / 2)puts("T");
else puts("F");
}
}
return 0;
}
L2-013 红色警报
并查集
用的暴力,每次丢一个城市就算一下集合个数
每一次比上一次集合个数多了1个以上就红警,因为把这个城市去掉,这个城市本身是单独集合,大于原来的集合+1就说明去掉的城市所在集合中其他城市连通性变了
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int p[N];
typedef pair<int, int> PII;
vector<PII> v;
bool lost[N];
int find(int x)
{
if(p[x] != x)p[x] = find(p[x]);
return p[x];
}
void join(int a, int b)
{
a = find(a), b = find(b);
p[a] = b;
}
int main()
{
int n, m;cin>>n>>m;
for(int i = 0; i < n; i ++)p[i] = i;
while(m --)
{
int l, r;cin>>l>>r;
v.push_back({l, r});
join(l, r);
}
int cnt = 0;
for(int i = 0; i < n; i ++)if(p[i] == i)cnt ++;
int k;cin>>k;
for(int j = 1; j <= k; j ++)
{
int a;cin>>a;
lost[a] = true;
for(int i = 0; i < n; i ++)p[i] = i;
for(auto [x, y] : v)
{
if(!lost[x] && !lost[y])
join(x, y);
}
int cnt0 = 0;
for(int i = 0; i < n; i ++)if(p[i] == i)cnt0 ++;
if(cnt0 > cnt + 1)printf("Red Alert: City %d is lost!", a);
else printf("City %d is lost.", a);
cout<<endl;
if(j == n)puts("Game Over.");
cnt = cnt0;
}
return 0;
}
L2-014 列车调度
二分 单调递增 O(nlogn)
对于每个编号,每次编号找比他大的最小编号(贪心),编号替代原先编号,没找到就新建平行铁轨。然后就形成了一个单调递增的数组,每次找最小的就是从前往后找,可使用upper_bound或lower_bound函数序号肯定各不相同,存在相同就用upper_bound
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int q[N];
int main()
{
int cnt = 0;
int n;cin>>n;
for(int i = 1; i <= n; i ++)
{
int x;cin>>x;
int pos = lower_bound(q, q + cnt, x) - q;
if(pos == cnt)q[cnt ++] = x;
else q[pos] = x;
}
cout<<cnt;
return 0;
}
L2-015 互评成绩
记录每人总分、最高分、最低分,总分减去最高最低,排序,输出平均
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, k;
cin>>n>>m>>k;
vector<double> v(n, 0), mx(n, 0), mn(n, 1e9);
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
{
double x;cin>>x;
v[i] += x;
mx[i] = max(mx[i], x);
mn[i] = min(mn[i], x);
}
for(int i = 0; i < n; i ++)v[i] -= mn[i] + mx[i];
sort(v.begin(), v.end(), greater<double>());
for(int i = k - 1; i >= 0; i --)
{
printf("%.3f", v[i] / (m - 2));
if(i)cout<<' ';
}
return 0;
}
L2-016 愿天下有情人都是失散多年的兄妹
小模拟,直接暴力五代往上收集家庭成员然后看是否重复就行,坑点就是
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
两个人是同辈,那就是可以是某些人父母辈,那么在统计信息的时候就要统计一下父母的性别
#include <bits/stdc++.h>
using namespace std;
struct node
{
int sex = -2, fa = -1, ma = -1;
}inf[100010];
int main()
{
int n;cin>>n;
for(int i = 0; i < n; i ++)
{
int id, sex, fa, ma;
char c;
cin>>id>>c>>fa>>ma;
sex = c == 'M' ? 1 : 0;
inf[id] = {sex, fa, ma};
if(~fa)inf[fa].sex = 1;
if(~ma)inf[ma].sex = 0;
}
int m;cin>>m;
while(m --)
{
int a, b;cin>>a>>b;
if(inf[a].sex == inf[b].sex)puts("Never Mind");
else
{
bool flag = true;
vector<int> l, r;
l.push_back(a), r.push_back(b);
vector<int>mem1 = l, mem2 = r;
for(int k = 0; k < 4; k ++)
{
vector<int> ll, rr;
for(auto i : l)
{
if(inf[i].sex == -2)continue;
if(inf[i].fa != -1)ll.push_back(inf[i].fa);
if(inf[i].ma != -1)ll.push_back(inf[i].ma);
}
for(auto i : r)
{
if(inf[i].sex == -2)continue;
if(inf[i].fa != -1)rr.push_back(inf[i].fa);
if(inf[i].ma != -1)rr.push_back(inf[i].ma);
}
l = ll, r = rr;
for(auto i : l)mem1.push_back(i);
for(auto i : r)mem2.push_back(i);
}
for(auto i : mem1)
for(auto j : mem2)
if(i == j)flag = false;
if(flag)puts("Yes");
else puts("No");
}
}
return 0;
}
L2-017 人以群分
水题
排序,一半(下取整)给内向,一半(上取整)给外向
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;cin>>n;
vector<int> v(n);
for(int i = 0; i < n; i ++)
cin>>v[i];
sort(v.begin(), v.end());
int mid = n / 2;
int sum = 0;
for(int i = 0; i < n; i ++)
{
if(i < mid)sum -= v[i];
else sum += v[i];
}
printf("Outgoing #: %d\n", (n + 1) / 2);
printf("Introverted #: %d\n", n / 2);
printf("Diff = %d", sum);
return 0;
}
L2-018 多项式A除以B
小模拟
用map分别存AB的指数和系数,按指数大到小排序,一直除并记录商就行了,余数为A
#include <iostream>
#include <map>
using namespace std;
map<int, double, greater<int>> a, b, s, a1, b1;
int main()
{
int n;cin>>n;
while(n --)
{
int x;cin>>x;
cin>>a[x];
}
cin>>n;
while(n --)
{
int x;cin>>x;
cin>>b[x];
}
while(a.begin() -> first >= b.begin() -> first)
{
int r = a.begin() -> first - b.begin() -> first;
double c = a.begin() -> second / b.begin() -> second;
s[r] = c;
for(auto i : b)
a[i.first + r] -= c * i.second;
a.erase(a.begin());
}
for(auto i : s)
if(abs(i.second) >= 0.05)a1[i.first] = i.second;
for(auto i : a)
if(abs(i.second) >= 0.05)b1[i.first] = i.second;
cout<<a1.size();
if(a1.size() != 0)
for(auto i : a1)printf(" %d %.1f", i.first, i.second);
else cout<<" 0 0.0";
cout<<endl;
cout<<b1.size();
if(b1.size() != 0)
for(auto i : b1)printf(" %d %.1f", i.first, i.second);
else cout<<" 0 0.0";
return 0;
}
L2-019 悄悄关注
小模拟
集合存关注,边读边记录点赞总次数和非关注人的点赞次数,最后根据平均值得到悄悄关注的人
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;cin>>n;
set<string> s;
while(n --)
{
string x;cin>>x;
s.insert(x);
}
vector<pair<string, int>>v, tmp;
int m;cin>>m;
int sum = 0;
for(int i = 0; i < m; i ++)
{
string a;int b;cin>>a>>b;
sum += b;
if(!s.count(a))v.push_back({a, b});
}
for(auto i : v)
if(i.second > sum / m)tmp.push_back(i);
v = tmp;
if(v.size() == 0)cout<<"Bing Mei You";
else
{
sort(v.begin(), v.end());
for(auto [x, y] : v)
cout<<x<<endl;
}
return 0;
}
L2-020 功夫传人
BFS
逆天坑点:祖师爷得道
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> g[N];
double va[N];
int main()
{
int n;
double z, r;
cin>>n>>z>>r;
for(int i = 0; i < n; i ++)
{
int k;cin>>k;
if(k)
while(k --)
{
int x;cin>>x;
g[i].push_back(x);
}
else
{
double x;cin>>x;
va[i] = x;
}
}
double ans = 0;
if(n == 1)ans = va[0] * z;
else
{
queue<int>q;
q.push(0);
va[0] = z;
r = 1.0 - r / 100.0;
while(q.size())
{
int t = q.front();
q.pop();
for(auto i : g[t])
{
ans += va[t] * r * va[i];
va[i] = va[t] * r;
q.push(i);
}
}
}
cout<<(int)ans;
return 0;
}
L2-021 点赞狂魔
自定义排序
标签出现次数平均值最小 点赞标签种类相同,k越大平均值越小
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;cin>>n;
vector<pair<int, string>>v;
while(n --)
{
string s;cin>>s;
int k;cin>>k;
set<int> S;
for(int i = 0; i < k; i ++)
{
int id;cin>>id;
S.insert(id);
}
v.push_back({S.size() * 1000 - k, s});
}
sort(v.begin(), v.end());
v.insert(v.begin(), 2, {0, "-"});
int m = v.size();
cout<<v[m - 1].second<<' '<<v[m - 2].second<<' '<<v[m - 3].second;
return 0;
}
L2-022 重排链表
数据结构 链表
读入的时候不仅记录正向,还记录反向,从两边往中间遍历即可
#include <iostream>
using namespace std;
const int N = 100010;
int ne[N], pre[N], e[N];
int main()
{
int st, end;
int n;
cin>>st>>n;
while(n --)
{
int a, b, c;cin>>a>>b>>c;
ne[a] = c;
e[a] = b;
if(c == -1)end = a;
else
pre[c] = a;
}
while(1)
{
if(st != end) printf("%05d %d %05d\n", end, e[end], st);
else break;
end = pre[end];
if(st != end) printf("%05d %d %05d\n", st, e[st], end);
else break;
st = ne[st];
}
printf("%05d %d -1", st, e[st]);
return 0;
}
L2-023 图着色问题
虚张声势题
看似图着色问题,实际只需要存下边,每次记录点颜色,然后去判断所有边上两点颜色是否相同
#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> pa;
int color[510];
int main()
{
int v, e, k;cin>>v>>e>>k;
while(e --)
{
int a, b;cin>>a>>b;
pa.push_back({a, b});
}
int n;cin>>n;
while(n --)
{
for(int i = 1; i <= v; i ++)cin>>color[i];
bool flag = true;
set<int> s;
for(int i = 1; i <= v; i ++)s.insert(color[i]);
if(k != s.size())flag = false;
for(auto [x, y] : pa)
if(color[x] == color[y])
flag = false;
if(flag)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
L2-024 部落
并查集 模板题
#include <iostream>
using namespace std;
int p[10010];
int find(int x)
{
if(p[x] != x)p[x] = find(p[x]);
return p[x];
}
int main()
{
int n;cin>>n;
for(int i = 1; i <= 10000; i ++)p[i] = i;
int mn = 0;
while(n --)
{
int k, r;cin>>k>>r;
mn = max(mn, r);
while(-- k)
{
int x;cin>>x;
mn = max(mn, x);
r = find(r), x = find(x);
if(r != x)p[r] = x;
}
}
int jihe = 0;
for(int i = 1; i <= mn; i ++)
if(p[i] == i)jihe ++;
cout<<mn<<' '<<jihe<<endl;
int q;cin>>q;
while(q --)
{
int a, b;cin>>a>>b;
a = find(a), b = find(b);
if(a == b)cout<<'Y'<<endl;
else cout<<'N'<<endl;
}
return 0;
}
L2-025 分而治之
看似并查集,实则不需要
直接存边,每次判断是否存在一条边满足边上两点都没被攻陷即可
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
vector<PII> v;
bool st[10010];
int main()
{
int n, m;cin>>n>>m;
while(m --)
{
int a, b;cin>>a>>b;
v.push_back({a, b});
}
int q;cin>>q;
while(q --)
{
int num;cin>>num;
memset(st, 0, sizeof st);
for(int i = 0; i < num; i ++)
{
int x;cin>>x;
st[x] = true;
}
bool flag = true;
for(auto [x, y] : v)
{
if(!st[x] && !st[y])
flag = false;
}
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
L2-026 小字辈
简单深搜,
记录辈分及辈分编号最大值
#include <bits/stdc++.h>
using namespace std;
int rk[100010];
vector<int> g[100010];
int mx = 1;
void dfs(int u, int r)
{
rk[u] = r;
mx = max(mx, r);
for(auto i : g[u])
dfs(i, r + 1);
}
int main()
{
int n;cin>>n;
int root;
for(int i = 1; i <= n; i ++)
{
int x;cin>>x;
if(x == -1)root = i;
else g[x].push_back(i);
}
dfs(root, 1);
cout<<mx<<endl;
bool flag = true;
for(int i = 1; i <= n; i ++)
if(rk[i] == mx)
{
if(!flag)cout<<' ';
flag = false;
cout<<i;
}
return 0;
}
L2-027 名人堂与代金券
自定义排序
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, g, k;
cin>>n>>g>>k;
vector<pair<int, string>> v(n + 1);
int sum = 0;
for(int i = 1; i <= n; i ++)
{
string s;cin>>s;
int num; cin>>num;
v[i] = {num, s};
if(num >= g)sum += 50;
else if(num >= 60)sum += 20;
}
cout<<sum<<endl;
sort(v.begin() + 1, v.end(), [&](pair<int, string> a, pair<int, string>b){
if(a.first != b.first)return a.first > b.first;
return a.second < b.second;
});
for(int i = 1; i <= k; i ++)
{
auto [x, y] = v[i];
cout<<i<<' '<<y<<' '<<x<<endl;
int j = i + 1;
while(j <= n && v[j].first == x)
{
cout<<i<<' '<<v[j].second<<' '<<v[j].first<<endl;
j ++;
}
i = j - 1;
}
return 0;
}
L2-028 秀恩爱分得快
小模拟
坑点:直接读数字的话读入-0的时候无法判断性别,得读入字符串然后转化
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
double g[N][N];
bool sex[N];
int toi(string s){//将字符串转化为正整数
int x=0;
if(s[0]=='-')for(int i=1;i<s.size();++i)x*=10,x+=s[i]-'0';
else for(int i=0;i<s.size();++i)x*=10,x+=s[i]-'0';
return x;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin>>n>>m;
while(m --)
{
int k;cin>>k;
double t = 1.0 / k;
vector<int> v;
for(int i = 0; i < k; i ++)
{
string s;cin>>s;
int x = toi(s);
if(s[0] == '-')sex[x] = true;
v.push_back(x);
}
for(int i = 0; i < v.size(); i ++)
for(int j = i + 1; j < v.size(); j ++)
{
if(sex[v[i]] == sex[v[j]])continue;
g[v[i]][v[j]] += t, g[v[j]][v[i]] += t;
}
}
string s;cin>>s;
int a = toi(s);
if(s[0] == '-')sex[a] = true;
cin>>s;
int b = toi(s);
if(s[0] == '-')sex[b] = true;
double m1 = 0, m2 = 0;
vector<int> pa, pb;
for(int i = 0; i < n; i ++)
{
if(sex[a] != sex[i] && m1 <= g[i][a])
{
if(m1 < g[i][a])pa.clear();
m1 = g[i][a];
pa.push_back(i);
}
if(sex[b] != sex[i] && m2 <= g[i][b])
{
if(m2 < g[i][b])pb.clear();
m2 = g[i][b];
pb.push_back(i);
}
}
if(m1 == g[a][b] && m1 == m2)
{
if(sex[a])cout<<'-'<<a<<' '<<b;
else cout<<a<<' '<<'-'<<b;
}
else
{
for(auto i : pa)
{
if(sex[a])cout<<'-'<<a<<' '<<i;
else cout<<a<<' '<<'-'<<i;
cout<<endl;
}
for(auto i : pb)
{
if(sex[b])cout<<'-'<<b<<' '<<i;
else cout<<b<<' '<<'-'<<i;
cout<<endl;
}
}
return 0;
}
L2-029 特立独行的幸福
暴力枚举每个数,不断做平方和,过程中得到的数都标记为不特立独行,最后得到1或者出现重复数就跳出循环
#include <bits/stdc++.h>
using namespace std;
map<int, int> mp;
bool st[10010];
bool is(int x)
{
for(int i = 2; i <= x / i; i ++)
if(x % i == 0)return false;
return true;
}
int main()
{
int l, r;cin>>l>>r;
for(int i = l; i <= r; i ++)
{
vector<int> v;
int t = i;
while(t != 1)
{
int sum = 0;
while(t)sum += (t % 10) * (t % 10), t /= 10;
t = sum;
if(find(v.begin(), v.end(), t) != v.end())break; //死循环
v.push_back(t);
st[t] = true; //t有依赖
}
if(t == 1)mp[i] = v.size();
}
for(auto [x, y] : mp)
if(!st[x])
{
if(is(x))cout<<x<<' '<<y * 2<<endl;
else cout<<x<<' '<<y<<endl;
}
if(!mp.size())cout<<"SAD";
return 0;
}
L2-030 冰岛人
记录一个人的性别和父亲,这里主要判断父族是否相同,存在乱伦情况
#include<bits/stdc++.h>
using namespace std;
struct node
{
char sex;
string fa;
};
map<string, node> mp;
bool f(string a, string b)
{
int i = 1, j = 1;
string A, B;
for(A = a; !A.empty(); A = mp[A].fa, i ++)
for(B = b, j = 1; !B.empty(); B = mp[B].fa, j ++)
{
if(i >= 5 && j >= 5)break;
if(A == B)return false;
}
return true;
}
int main()
{
int n;cin>>n;
while(n --)
{
string a, b;cin>>a>>b;
if(b.back() == 'n')mp[a] = {'m', b.substr(0, b.size() - 4)};
else if(b.back() == 'r')mp[a] = {'f', b.substr(0, b.size() - 7)};
else mp[a].sex = b.back();
}
int m;cin>>m;
while(m --)
{
string a, b, c;cin>>a>>c>>b>>c;
if(!mp.count(a) || !mp.count(b))puts("NA");
else if(mp[a].sex == mp[b].sex)puts("Whatever");
else cout<<(f(a, b) ? "Yes" : "No")<<endl;
}
return 0;
}
L2-031 深入虎穴
BFS 模板
#include <bits/stdc++.h>
using namespace std;
int d[100010];
vector<int> g[100010];
bool st[100010];
int ans = 0, id;
void bfs(int u)
{
queue<int>q;
q.push(u);
while(q.size())
{
int t = q.front();
q.pop();
for(auto i : g[t])
{
d[i] = d[t] + 1;
if(ans < d[i])
{
ans = d[i];
id = i;
}
q.push(i);
}
}
}
int main()
{
int n;cin>>n;
for(int i = 1; i <= n; i ++)
{
int k;cin>>k;
while(k --)
{
int x;cin>>x;
g[i].push_back(x);
st[x] = true;
}
}
int root = 1;
while(st[root])root ++;
id = root;
bfs(root);
cout<<id;
return 0;
}
L2-032 彩虹瓶
模拟栈
每次从前往后依次处理,如果栈里面有需要的编号就出栈,没有就按顺序找,匹配就找下一个编号,不匹配就放栈里
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m, k;
cin>>n>>m>>k;
while(k --)
{
stack<int> s;
bool flag = true;
vector<int> v(n + 1);
for(int i = 1; i <= n; i ++)cin>>v[i];
int num = 1;
for(int i = 1; i <= n; i ++)
{
if(v[i] == num)num ++;
else
{
while(s.size() && s.top() == num)
{
s.pop();
num ++;
}
s.push(v[i]);
if(s.size() > m)flag = false;
}
}
while(s.size() && s.top() == num)
{
s.pop();
num ++;
}
if(s.size())flag = false;
if(flag)puts("YES");
else puts("NO");
}
return 0;
}
L2-033 简单计算器
模拟栈
#include <bits/stdc++.h>
using namespace std;
int main()
{
stack<int>s;
stack<char>op;
int n;cin>>n;
for(int i = 1; i <= n; i ++)
{
int x;cin>>x;
s.push(x);
}
for(int i = 1; i < n; i ++)
{
char c;cin>>c;
op.push(c);
}
while(op.size())
{
int a, b;
a = s.top();
s.pop();
b = s.top();
s.pop();
char c = op.top();op.pop();
int num;
if(c == '+')num = b + a;
if(c == '-')num = b - a;
if(c == '*')num = b * a;
if(c == '/')
{
if(a == 0)
{
printf("ERROR: %d/0", b);
return 0;
}
num = b / a;
}
s.push(num);
}
cout<<s.top();
return 0;
}
L2-034 口罩发放
中模拟
需要记下姓名、编号、状况、时间、申请顺序,排序按照时间和申请顺序排列,
坑点:判断是否申请超过p天不是判断p*24*60分钟而是直接判断日期天
#include <bits/stdc++.h>
using namespace std;
struct node
{
string name, id;
int con;
int ti;
int sx;
bool operator < (const node & W)
{
if(ti != W.ti)return ti < W.ti;
return sx < W.sx;
}
};
bool check(string id) // 检查身份证是否合法
{
int len = id.size();
if (len != 18) return false;
else
{
for (int i = 0; i < len; i++)
if (id[i] < '0' || id[i] > '9')
return false;
}
return true;
}
map<string, int>last;
vector<string>v;
map<string, string>mp;
int main()
{
int d, p;cin>>d>>p;
for(int day = 1; day <= d; day ++) // 遍历每一天
{
int n, k;cin>>n>>k;
vector<node>peo;
for(int j = 0; j < n; j ++)
{
string a, b;cin>>a>>b;
int con, h, m;char c;
cin>>con>>h>>c>>m;
if(!check(b))continue;
mp[b] = a; // 正确id对应名字
if(con == 1 && find(v.begin(), v.end(), b) == v.end())v.push_back(b); // 收集患病数据
peo.push_back({a, b, con, h * 60 + m, j});
}
sort(peo.begin(), peo.end()); //按时间和申请顺序排序
for(int i = 0; i < peo.size(); i ++)
{
string a = peo[i].name, b = peo[i].id;
int con = peo[i].con, t = peo[i].ti;
if(k == 0)continue; //当天名额发完
if(last.count(b) && last[b] + p >= day)continue; //申请过并且申请时间太短
last[b] = day;//更新申请时间
k --;
cout<<a<<' '<<b<<endl;//发放口罩
}
}
for(auto a : v)
cout<<mp[a]<<' '<<a<<endl;
return 0;
}
L2-035 完全二叉树的层序遍历
这个比较新奇,对输入dfs即可,深读
#include <iostream>
using namespace std;
int tr[100];
int n;
void create(int u)
{
if(u > n)return ;
create(u << 1);
create(u << 1 | 1);
cin>>tr[u];
}
int main()
{
cin>>n;
create(1);
for(int i = 1; i <= n; i ++)
{
if(i != 1)cout<<' ';
cout<<tr[i];
}
return 0;
}
L2-036 网红点打卡攻略
最小生成树?prim?nonono
题目已经把方案给了,直接算就行了
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int g[N][N];
int main()
{
memset(g, 0x3f, sizeof g);
int n, m;cin>>n>>m;
while(m --)
{
int a, b, c;cin>>a>>b>>c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
int k;cin>>k;
int cnt = 0;
int id, cost = 1e9;
for(int i = 1; i <= k; i ++)
{
bool flag = true;
int num;cin>>num;
vector<int> v;
v.push_back(0);
int mon = 0;
bool st[N] = {0};
for(int j = 0; j < num; j ++)
{
int x;cin>>x;
if(g[v[j]][x] == 0x3f3f3f3f)flag = false;
st[x] = true;
v.push_back(x);
mon += g[v[j]][x];
}
if(g[v[v.size() - 1]][0] == 0x3f3f3f3f)flag = false;
mon += g[v[v.size() - 1]][0];
if(num != n)continue;
for(int i = 1; i <= n; i ++)if(!st[i])flag = false;
if(!flag)continue;
cnt ++;
if(mon < cost)
{
cost = mon;
id = i;
}
}
cout<<cnt<<endl<<id<<' '<<cost;
return 0;
}
L2-037 包装机
模拟栈
#include <bits/stdc++.h>
using namespace std;
int n, m, mx;
stack<char> stk[110];
int main()
{
cin>>n>>m>>mx;
for(int i = 1; i <= n; i ++)
{
string s;cin>>s;
for(int j = s.size() - 1; j >= 0; j --)
stk[i].push(s[j]);
}
int op;
stack<char> s;
while(cin >> op, op != -1)
{
if(op > 0)
{
if(!stk[op].size())continue;
if(s.size() >= mx && s.size())// 筐满
{
cout<<s.top();
s.pop();
}
s.push(stk[op].top());
stk[op].pop();
}
else
{
if(s.size()) // 筐不空
{
cout<<s.top();
s.pop();
}
}
}
return 0;
}
L2-038 病毒溯源
找到根,深搜找最长路
#include <bits/stdc++.h>
using namespace std;
vector<int> g[10010];
int d[10010];
int ans = 0, ed;
int pre[10010];
int root;
bool st[10010];
void dfs(int u)
{
for(int i : g[u])
{
d[i] = d[u] + 1;
pre[i] = u;
dfs(i);
if(d[i] > ans)
{
ans = d[i];
ed = i;
}
}
}
int main()
{
int n;cin>>n;
for(int i = 0; i < n; i ++)
{
int k;cin>>k;
while(k --)
{
int x;cin>>x;
g[i].push_back(x);
st[x] = true;
}
sort(g[i].begin(), g[i].end());
}
root = 0;
while(st[root])root ++;
dfs(root);
cout<<ans + 1<<endl;
vector<int> v;
while(ed != root)
{
v.push_back(ed);
ed = pre[ed];
}
cout<<root;
for(int i = v.size() - 1; i >= 0; i --)
cout<<' '<<v[i];
return 0;
}
L2-039 清点代码库
相同输入输出视为一个模块,那么我们用map对每一行做映射,记录次数即可
#include <bits/stdc++.h>
using namespace std;
bool cmp(pair<vector<int>, int> a, pair<vector<int>, int> b)
{
auto [x, y] = a;
auto [xx, yy] = b;
if(y != yy)return y > yy;
for(int i = 0; i < x.size(); i ++)
{
if(x[i] != xx[i])
return x[i] < xx[i];
}
}
map<vector<int>, int> cnt;
int main()
{
int n, m;
cin>>n>>m;
for(int i = 0; i < n; i ++)
{
vector<int> v(m);
for(int j = 0; j < m; j ++)
cin>>v[j];
cnt[v] ++;
}
vector<pair<vector<int>, int>> ve;
for(auto i : cnt)ve.push_back(i);
sort(ve.begin(), ve.end(), cmp);
cout<<ve.size()<<endl;
for(auto [x, y] : ve)
{
cout<<y;
for(int i = 0; i < x.size(); i ++)
cout<<" "<<x[i];
cout<<endl;
}
return 0;
}
L2-040 哲哲打游戏
小模拟
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> g[N];
int d[N];
int main()
{
int n, m;cin>>n>>m;
for(int i = 1; i <= n; i ++)
{
int k;cin>>k;
while(k --)
{
int x;cin>>x;
g[i].push_back(x);
}
}
int now = 1;
while(m --)
{
int op;cin>>op;
int x;cin>>x;
if(!op)
now = g[now][x - 1];
else if(op == 1)
{
cout<<now<<endl;
d[x] = now;
}
else
now = d[x];
}
cout<<now;
return 0;
}
L2-041 插松枝
中模拟
盒子是一个栈,推送器用队列表示
以栈和队列中都没东西作为循环结束
#include <bits/stdc++.h>
using namespace std;
stack<int> s; //盒子
queue<int> q;
vector<int>ans;
int n, m, k;
bool check()
{
if(!ans.size())return false;
if(s.size() == m && s.top() > ans.back() && q.size() && q.front() > ans.back())return true;//1 盒子满 推送器没法用
if(s.size() && s.top() > ans.back() && !q.size())return true; //2 盒子有但不符合,推送器空
if(ans.size() == k)return true; //3 松枝干满
return false;
}
int main()
{
cin>>n>>m>>k;
for(int i = 0; i < n; i ++)
{
int x;cin>>x;
q.push(x);
}
while(s.size() || q.size())
{
if(check())
{
for(int i = 0; i < ans.size(); i ++)
{
if(i)cout<<' ';
cout<<ans[i];
}
cout<<endl;
ans.clear();
}
if(s.size() && (!ans.size() || s.top() <= ans.back())) //用盒子
{
ans.push_back(s.top());
s.pop();
}
else if(q.size() && (!ans.size() || q.front() <= ans.back())) // 用推送
{
ans.push_back(q.front());
q.pop();
}
else if(q.size() && s.size() < m) //放盒子
{
s.push(q.front());
q.pop();
}
}
if(ans.size())
for(int i = 0; i < ans.size(); i ++)
{
if(i)cout<<' ';
cout<<ans[i];
}
return 0;
}
L2-042 老板的作息表
小模拟
对时间区间排个序,然后按时间处理
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
vector<PII> v;
int main()
{
int n;cin>>n;
for(int i = 0; i < n; i ++)
{
int a, b, c;
char x;
cin>>a>>x>>b>>x>>c;
int t1, t2;
t1 = a * 3600 + b * 60 + c;
cin>>x;
cin>>a>>x>>b>>x>>c;
t2 = a * 3600 + b * 60 + c;
v.push_back({t1, t2});
}
sort(v.begin(), v.end());
int last = 0;
for(int i = 0; i < n; i ++)
{
auto [x, y] = v[i];
if(x != last)
{
int a1 = last / 3600, a2 = last / 60 % 60, a3 = last % 60;
int b1 = x / 3600, b2 = x / 60 % 60, b3 = x % 60;
printf("%02d:%02d:%02d - %02d:%02d:%02d\n", a1, a2, a3, b1, b2, b3);
}
last = y;
}
if(last != 24 * 3600 - 1)
{
int a1 = last / 3600, a2 = last / 60 % 60, a3 = last % 60;
printf("%02d:%02d:%02d - %02d:%02d:%02d\n", a1, a2, a3, 23, 59, 59);
}
return 0;
}
L2-043 龙龙送外卖
dfs
首先存下每个结点的父结点、子结点,用子结点计算深度,即与外卖站的距离,
然后对于每个新增结点,往上找父亲结点,将路过的没遍历过的点都标记,直到遇到标记过的点,距离加上往上找的次数*2,相当于一个来回,最后输出减去回去的长度即可
即将经过的站作为新树树干,新增一个结点要连到这个树干上
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> son[N];
int fa[N];
int depth[N];
void dfs(int u, int d)
{
depth[u] = d;
for(auto i : son[u])
dfs(i, d + 1);
}
int ans;
bool st[N];
void dfs2(int u)
{
if(st[u])return;
st[u] = true;
ans += 2;
dfs2(fa[u]);
}
int main()
{
int n, m;cin>>n>>m;
int root;
for(int i = 1; i <= n; i ++)
{
int x;cin>>x;
if(x == -1)root = i;
else son[x].push_back(i), fa[i] = x;
}
dfs(root, 0);
int mx = 0; // 回来的长度
st[root] = true;
while(m --)
{
int x;cin>>x;
mx = max(mx, depth[x]);
if(st[x])cout<<ans - mx<<endl;
else
{
dfs2(x);
cout<<ans-mx<<endl;
}
}
return 0;
}
L2-044 大众情人
floyd
距离什么的有点混,g[a][b]是a眼中b的距离,也就是对于b来说的,求对b来说最大的异性a的距离就等价于异性缘
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int g[N][N];// i眼中的j
char sex[N];
int main()
{
int n;cin>>n;
memset(g, 0x3f, sizeof g);
for(int i = 1; i <= n; i ++)
{
cin>>sex[i];
int k;cin>>k;
while(k --)
{
int a, b;char c;
cin>>a>>c>>b;
g[i][a] = b;
}
}
for(int k = 1; k <= n; k ++)
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
vector<int> v1, v2;
int m1 = 0x3f3f3f3f, m2 = m1;
for(int i = 1; i <= n; i ++)
{
int tmp = -1;
for(int j = 1; j <= n; j ++)
if(sex[i] != sex[j])//如果有人不认识异性也算在最大距离里
tmp = max(tmp, g[j][i]);//求i的最小异性缘,最大距离
if(~tmp)
{
if(sex[i] == 'F')
{
if(tmp < m1)
{
v1 = {i};
m1 = tmp;
}
else if(tmp == m1)v1.push_back(i);
}
else
{
if(tmp < m2)
{
v2 = {i};
m2 = tmp;
}
else if(tmp == m2)v2.push_back(i);
}
}
}
for(int i = 0; i < v1.size(); i ++)
{
if(i)cout<<' ';
cout<<v1[i];
}
cout<<endl;
for(int i = 0; i < v2.size(); i ++)
{
if(i)cout<<' ';
cout<<v2[i];
}
return 0;
}
L2-045 堆宝塔
模拟栈
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;cin>>n;
queue<int> q;
while(n --)
{
int x;cin>>x;
q.push(x);
}
stack<int> a, b;
int mx = 0, cnt = 0;
while(q.size())
{
auto t = q.front();
q.pop();
if(a.empty() || a.top() > t)
a.push(t);
else
{
if(b.empty() || b.top() < t)
b.push(t);
else
{
cnt ++;
mx = max(mx, (int)a.size());
while(a.size())a.pop();
while(b.size() && b.top() > t)
{
a.push(b.top());
b.pop();
}
a.push(t);
}
}
}
if(a.size())cnt ++, mx = max(mx, (int)a.size());
if(b.size())cnt ++, mx = max(mx, (int)b.size());
cout<<cnt<<' '<<mx;
return 0;
}
L2-046 天梯赛的赛场安排
小模拟
用优先队列暴力模拟即可
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, string> PIS;
int main()
{
int n, c;
cin>>n>>c;
vector<string> v;
map<string, int> mp;
priority_queue<PIS, vector<PIS>>heap;
vector<int> kong;
while(n --)
{
string s;int x;cin>>s>>x;
v.push_back(s);
heap.push({x, s});
}
int cnt = 0;
while(heap.size())
{
auto [x, y] = heap.top();
heap.pop();
if(x >= c)
{
cnt ++;
mp[y] ++;
x -= c;
if(x)heap.push({x, y});
}
else
{
mp[y] ++;
int id = -1;
for(int i = 0; i < kong.size(); i ++)
if(kong[i] >= x)
{
id = i;
kong[i] -= x;
break;
}
if(~id)continue;
kong.push_back(c - x);
cnt ++;
}
}
for(auto i : v)
cout<<i<<' '<<mp[i]<<endl;
cout<<cnt;
return 0;
}
L2-047 锦标赛
新增一层,将每场比赛的结果按顺序往下存下来,然后dfs暴搜
#include <iostream>
using namespace std;
int k;
int w[(1 << 19) + 10];
bool dfs(int u, int depth, int val)
{
if(depth == k)
{
if(w[u])return false;
if(u & 1 == 0) // 偶数
{
w[u] = val;
return true;
}
else // 奇数
{
if(w[u - 1] > val)return false;
w[u] = val;
return true;
}
}
if(val >= w[u] && dfs(u * 2, depth + 1, val))
{
w[u] = val;
return true;
}
if(val >= w[u] && dfs(u * 2 + 1, depth + 1, val))
{
w[u] = val;
return true;
}
return false;
}
int main()
{
cin>>k;
for(int i = 1; i <= k; i ++)
{
int l = 1 << (k - i), r = l * 2 - 1;
for(int j = l; j <= r; j ++)
{
int x;cin>>x;
if(!dfs(j, k - i, x))
{
cout<<"No Solution";
return 0;
}
}
}
int x;cin>>x;
if(!dfs(1, 0, x))
{
cout<<"No Solution";
return 0;
}
for(int i = 1 << k; i < 1 << k + 1; i ++)
cout<<w[i]<<' ';
return 0;
}
L2-048 寻宝图
flood fill 模板题
#include <bits/stdc++.h>
using namespace std;
int dx[] = {0, 1, 0, -1, 0}, dy[] = {-1, 0, 1, 0, 0};
int main()
{
int n, m;cin>>n>>m;
vector<string> g(n);
for(int i = 0; i < n; i ++)cin>>g[i];
int cnt = 0, val = 0;
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
if(g[i][j] != '0')
{
cnt ++;
bool flag = false;
queue<pair<int, int>> q;
q.push({i, j});
while(q.size())
{
auto [x, y] = q.front();
q.pop();
for(int k = 0; k < 5; k ++)
{
int a = x + dx[k], b = y + dy[k];
if(a < 0 || a >= n || b < 0 || b >= m)continue;
if(g[a][b] == '0')continue;
if(g[a][b] > '1')flag = true;
q.push({a, b});
g[a][b] = '0';
}
}
if(flag)val ++;
}
cout<<cnt<<' '<<val;
return 0;
}
L2-049 鱼与熊掌
物品对人连边 + 二分搜索
#include <bits/stdc++.h>
using namespace std;
vector<int> g[100010];
int main()
{
int n, m;cin>>n>>m;
for(int i = 1; i <= n; i ++)
{
int k;cin>>k;
while(k --)
{
int x;cin>>x;
g[x].push_back(i);
}
}
int q;cin>>q;
while(q --)
{
int cnt = 0;
int a, b;cin>>a>>b;
for(auto i : g[a])
{
int pos = lower_bound(g[b].begin(), g[b].end(), i) - g[b].begin();
if(pos == g[b].size())continue;
if(g[b][pos] == i)cnt ++;
// cout<<i<<' '<<g[b][pos]<<endl;
}
cout<<cnt<<endl;
}
}
L2-050 懂蛇语
map 单词首字母的组合映射string数组,然后一个一个查
#include <bits/stdc++.h>
using namespace std;
map<string, vector<string>>mp;
int main()
{
int n; cin>>n;
getchar();
while(n --)
{
string str;
getline(cin,str);
stringstream ss(str);
string s, a;
while(ss>>a) s+=a[0];
mp[s].push_back(str);
}
int q;cin>>q;
getchar();
while(q --)
{
string s;
getline(cin, s);
stringstream ss(s);
string name, a;
while(ss>>a) name+=a[0];
// cout<<s<<" ?? "<<name<<endl;
if(mp.count(name))
{
vector<string> v = mp[name];
sort(v.begin(), v.end());
cout<<v[0];
for(int i = 1; i < v.size(); i ++)
cout<<'|'<<v[i];
cout<<endl;
}
else
cout<<s<<endl;
}
return 0;
}
L2-051 满树的遍历
找到根,深搜判断是否非叶结点度相同,深搜输出前序遍历结果
#include <bits/stdc++.h>
using namespace std;
vector<int> g[100010];
bool flag = true;
int ans = -1;
void dfs(int u)
{
if(g[u].empty())return ;
if(ans != -1 && ans != g[u].size())flag = false;
ans = max(ans, (int)g[u].size());
for(auto i : g[u])
dfs(i);
}
void dfs2(int u)
{
for(auto i : g[u])
{
cout<<' '<<i;
dfs2(i);
}
}
int main()
{
int n;cin>>n;
int root;
for(int i = 1; i <= n; i ++)
{
int x;cin>>x;
if(!x)root = i;
else g[x].push_back(i);
}
dfs(root);
if(ans == -1)ans = 0;
cout<<ans<<' '<<(flag ? "yes" : "no")<<endl;
cout<<root;
dfs2(root);
return 0;
}
L2-052 吉利矩阵
暴力深搜,将矩阵填满就check 计算量16 * 2 ^ 8
#include <iostream>
using namespace std;
int g[10][10];
int sum, n;
int ans = 0;
bool check(int x, int y)
{
int cnt = 0;
for(int i = 1; i <= x; i ++)
cnt += g[i][y];
if(cnt > sum)return false;
if(x == n && cnt != sum)return false;
cnt = 0;
for(int i = 1; i <= y; i ++)
cnt += g[x][i];
if(cnt > sum)return false;
if(y == n && cnt != sum)return false;
return true;
}
void dfs(int x, int y)
{
for(int i = 0; i <= sum; i ++)
{
g[x][y] = i;
if(!check(x, y))continue;
if(x == n && y == n){ans ++;return ;}
if(y == n)dfs(x + 1, 1);
else dfs(x, y + 1);
}
}
int main()
{
cin>>sum>>n;
dfs(1, 1);
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号