文章检索器
赛后感想
据说今年的天梯赛比以往简单,咱也不知道,没啥感觉,第一次参加天梯赛,所以并不晓得以往正式赛难度如何,反正我这次是失败告终了,难受啊,本来拿个个人三等应该是势在必得的,遇到病毒之后惨了,强行卡了一个多小时,斩获0分😶。哎,,不说了,都是辛酸泪啊。。。菜鸡流泪😭。
赛后补题
那就先来解决病毒溯源这个毒瘤吧。
看清题目,看清题目,看清题目。。。
(ps:如果长链不唯一,输出最小序列)
Problem 1 L2-038 病毒溯源(25)
补题传送门
解题思路:
就是直接暴力的思路。病毒源只有一个,可以记录顶点的度数来寻找病毒源。找到病毒源之后,用
B
F
S
BFS
BFS 求一个单源最长路即可。用
f
a
[
i
]
fa[i]
fa[i]数组来记录第
i
i
i 个节点的父亲节点。根据父亲节点与子节点之间的关系,逆向寻找路径,用二维
v
e
c
t
o
r
vector
vector 数组记录所有可行方案,再来个排序输出第一个即为最终答案。
C++ AC代码:
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
vector<int> v[10010];
int d[10010], dist[10010], fa[10010];
vector<vector<int> > res;
int ans, root;
bool vis[10010];
void bfs()
{
queue<int> q;
q.push(root);
dist[root] = 1;
while (q.size())
{
int u = q.front();q.pop();
for (int i = 0;i < v[u].size();i++)
{
int j = v[u][i];
if (dist[j] < dist[u] + 1)
{
dist[j] = dist[u] + 1;
fa[j] = u;
q.push(j);
}
}
}
}
bool cmp(vector<int> x, vector<int> y)
{
for (int i = 0;i < x.size();i++)
{
if (x[i] != y[i]) return x[i] < y[i];
}
}
int main()
{
int n; scanf("%d", &n);
for (int i = 0;i < n;i++)
{
int k; scanf("%d", &k);
d[i]++;
for (int j = 0;j < k;j++)
{
int x; scanf("%d", &x);
v[i].push_back(x);
d[x]++;
}
}
while (d[root] != 1) root++;
bfs();
fa[root] = root;
int pos;
for (int i = 0;i < n;i++)
{
ans = max(ans, dist[i]);
}
printf("%d\n", ans);
for (int i = 0;i < n;i++)
{
if (dist[i] == ans)
{
vector<int> tmp;
int rt = i;
while (fa[rt] != rt)
{
tmp.push_back(rt);
rt = fa[rt];
}
tmp.push_back(root);
reverse(tmp.begin(), tmp.end());
res.push_back(tmp);
}
}
sort(res.begin(), res.end(), cmp);
for (int i = 0;i < res[0].size();i++)
{
printf("%d", res[0][i]);
if (i < res[0].size() - 1) printf(" ");
}
return 0;
}
Problem 2 L2-037 包装机(25)
补题传送门
这个题是个简单的队列与栈的操作,不做过多解释,直接放上我的代码吧。
C++ AC代码
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
queue<char> q[110];
int op[100010];
char st[110];//框
int s;
int main()
{
int N, M, S; cin >> N >> M >> S;
for (int i = 1;i <= N;i++)
{
string str; cin >> str;
for (int j = 0;j < str.size();j++) q[i].push(str[j]);
}
M = 0;
while (1)
{
int x; cin >> x;
if (x == -1) break;
op[++M] = x;
}
vector<char> res;//传送带上物品
for (int i = 1;i <= M;i++)
{
int k = op[i];
if (k == 0)
{
if (s) res.push_back(st[s--]);
}
else {
if (q[k].empty()) continue;
if (s < S){
st[++s] = q[k].front();q[k].pop();
}
else {
res.push_back(st[s--]);
st[++s] = q[k].front();q[k].pop();
}
}
}
for (int i = 0;i < res.size();i++)
{
cout << res[i];
}
return 0;
}
Problem 3 L2-039 清点代码库(25)
补题传送门
解题思路:
这个题还真就长见识了,两个
v
e
c
t
o
r
vector
vector 容器可以直接比较大小,比较规则是从前往后遍历每一个元素,返回第一个不相等的元素的比较结果。可以放进
s
e
t
set
set 中,也可以放进
m
a
p
map
map 中。这样的话,就很好操做了。一开始我使用
m
a
p
map
map 记录出现的次数,利用
s
e
t
set
set 去重,但可能是卡
m
a
p
map
map 了,只能得到
21
21
21 分。得到满分的做法是先排序,相同的就会在相邻的位置,从前往后遍历,记录出现次数,用结构体存储可以比较方便的实现排序及计数。
注意:这个题会卡
c
i
n
cin
cin 和
c
o
u
t
cout
cout.
C++ Score 25:
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
vector<vector<int> > v;
struct node {
int sum;
vector<int> tmp;
}st[10010];
int s;
bool cmp(node x, node y)
{
if (x.sum != y.sum) return x.sum > y.sum;
else return x.tmp < y.tmp;
}
int main()
{
int n, m; scanf("%d%d", &n, &m);
for (int i = 0;i < n;i++)
{
vector<int> tmp;
for (int j = 0;j < m;j++)
{
int x; scanf("%d", &x);
tmp.push_back(x);
}
v.push_back(tmp);
}
sort(v.begin(), v.end());
st[++s] = { 1,v[0] };
for (int i = 1;i < n;i++)
{
if (v[i] != v[i - 1])
{
st[++s] = { 1,v[i] };
}
else st[s].sum++;
}
sort(st + 1, st + s + 1, cmp);
printf("%d\n", s);
for (int i = 1;i <= s;i++)
{
printf("%d", st[i].sum);
for (int j = 0;j < st[i].tmp.size();j++)
{
printf(" %d", st[i].tmp[j]);
}
if (i < s) printf("\n");
}
return 0;
}
C++ Score 21:
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
vector<int> v[10010];
map<vector<int>, int> mp;
set<vector<int> > s;
bool cmp(vector<int> x, vector<int> y)
{
if (mp[x] != mp[y]) return mp[x] > mp[y];
return x < y;
}
int main()
{
int n, m; scanf("%d%d",&n,&m);
for (int i = 0;i < n;i++)
{
for (int j = 0;j < m;j++)
{
int x; scanf("%d",&x);
v[i].push_back(x);
}
mp[v[i]]++;
s.insert(v[i]);
}
vector<vector<int> > res;
for (auto item : s) {
res.push_back(item);
}
sort(res.begin(), res.end(), cmp);
/*for (int i = 0;i < res.size();i++)
{
for (int j = 0;j < res[i].size();j++)
{
cout << res[i][j] << " ";
}
cout << endl;
}*/
printf("%d\n",res.size());
for (int i = 0;i < res.size();i++)
{
printf("%d",mp[res[i]]);
for (int j = 0;j < res[i].size();j++)
{
printf(" %d",res[i][j]);
}
if (i < res.size() - 1) printf("\n");
}
return 0;
}
Problem 4 L2-040 哲哲打游戏(25)
补题传送门
阅读理解题,按照题目描述模拟就OK,so easy 呀。无语了,当时就应该先开这个题的,策略问题,当时看到题目描述有点长,就习惯性的略过了,直接留到了后面,然而到后面之后根本没心思冷静下来读题,难受。
C++ Score 25:
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int N = 100010;
vector<int> v[N];
int mark[N];
int main()
{
int n, m; scanf("%d%d", &n, &m);
for (int i = 1;i <= n;i++)
{
int k; scanf("%d", &k);
v[i].push_back(0);
for (int j = 1;j <= k;j++)
{
int x;scanf("%d", &x);
v[i].push_back(x);
}
}
int now = 1;
while (m--)
{
int op, x; scanf("%d%d", &op, &x);
if (op == 1)
{
mark[x] = now;
printf("%d\n",mark[x]);
}
else if(op == 0){
now = v[now][x];
}
else if (op == 2)
{
now = mark[x];
}
}
printf("%d", now);
return 0;
}
Problem 5 L3-029 还原文件(30)
补题传送门
解题思路:
1、非满分做法,直接暴力,就像字符串匹配那样,只要遇到第一个与当前纸片匹配的片段,就记录一下匹配的位置。之后按照位置排序,输出即可,骗分大法好,这样暴力直接白嫖26分,也是蛮不错滴。
2、满分做法真的没想到,竟然可以直接爆搜,而且还是跑的非常快的那种。听了y总的直播讲解后,恍然大悟啊。数据范围不是很大,有且仅存在一个解,所以直接
d
f
s
dfs
dfs 搜索即可,若当前片段能够和原串匹配,记录位置,搜索下一个片段。快速判断两个片段是否匹配时,需要用到字符串哈希的知识。代码实现不算很难,下面放上我的30分代码。
C++ Score 30:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int N = 100010,M = 110;
const int P = 131;
ull h[N],p[N];
ull g[M];//存储m个小碎片的哈希值
int width[M];//存储小碎片的宽度
int n,m;
ull get_hash(int l,int r)
{
return h[r] - h[l - 1] * p[r - l + 1];
}
bool vis[N];
int ans[M];
void dfs(int t,int start)//开始匹配的起点
{
if(t > m){
for(int i = 1;i <= m;i++)
{
printf("%d",ans[i]);
if(i < m) printf(" ");
}
return;
}
for(int i = 1;i <= m;i++)
{
if(!vis[i] && g[i] == get_hash(start,start + width[i] - 1))
{
vis[i] = true;
ans[t] = i;
dfs(t + 1,start + width[i] - 1);
vis[i] = false;
ans[t] = 0;
}
}
}
int main()
{
p[0] = 1;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
int x; scanf("%d",&x);
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + x + 1;
}
scanf("%d",&m);
for(int i = 1;i <= m;i++)
{
int len; scanf("%d",&len);
width[i] = len;
for(int j = 1;j <= len;j++)
{
int x; scanf("%d",&x);
g[i] = g[i] * P + x + 1;
}
}
dfs(1,1);
return 0;
}
C++ Score 26:
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int N = 100010;
int a[N], n;
struct node {
int id;
int xh;
vector<int> v;
}st[N];
void deal(node& x)
{
for (int i = x.v.size();i <= n;i++)
{
bool flag = true;
for (int j = 0;j < x.v.size();j++)
{
if (x.v[j] != a[i - x.v.size() + j + 1])
{
flag = false;
break;
}
}
if (flag)
{
x.id = i;
return;
}
}
}
bool cmp(node x, node y)
{
return x.id < y.id;
}
int main()
{
scanf("%d", &n);
for (int i = 1;i <= n;i++) scanf("%d", &a[i]);
int m; scanf("%d", &m);
for (int i = 1;i <= m;i++)
{
int num; scanf("%d", &num);
vector<int> tmp;
for (int j = 1;j <= num;j++)
{
int x; scanf("%d", &x);
tmp.push_back(x);
}
st[i] = { i,i,tmp };
deal(st[i]);
}
sort(st + 1, st + m + 1, cmp);
for (int i = 1;i <= m;i++)
{
printf("%d", st[i].xh);
if (i < m) printf(" ");
}
return 0;
}
更新ing。。。
最近更新时间:2021.4.29.00:11✌