西南民族大学2023天梯选拔赛
L1-1 谢谢卡尔!
print("谢谢卡尔!\\(>_<)/")
L1-2 现在是,幻想时间!
#include <bits/stdc++.h>
using namespace std;
int main(){
double a , b;
cin >> a >> b;
printf("%.3lf" , a / b );
}
L1-3 你是来陪可莉炸鱼的吗?
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, res = 0;
cin >> n;
for (int x; n; n--) {
cin >> x;
if (x < 100) res += 1;
else if (x < 200) res += 2;
else if (x < 300) res += 5;
else if (x < 400) res += 10;
else res += 15;
}
cout << res;
}
L1-4 扫雷游戏
#include <bits/stdc++.h>
using namespace std;
int f[15][15], n, m;
const int dx[] = {0, 0, 1, -1, 1, 1, -1, -1};
const int dy[] = {1, -1, 0, 0, 1, -1, 1, -1};
int main() {
cin >> n >> m;
string s;
for (int i = 1; i <= n; i++) {
cin >> s;
for (int j = 1; j <= m; j++) {
if (s[j - 1] == '.') continue;
f[i][j] = INT_MIN;
for (int k = 0; k < 8; k++)
f[i + dx[k]][j + dy[k]]++;
}
}
for( int i = 1 ; i <= n ; i ++ ){
for( int j = 1 ; j <= m ; j ++ ){
if( f[i][j] == 0 ) cout << ".";
else if( f[i][j] < 0 ) cout << "*";
else cout << f[i][j];
}
cout << "\n";
}
}
L1-5 史莱姆
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read();
vector<char> b;
string s;
cin >> s;
for( auto i : s ){
if( b.empty() ) b.push_back(i);
else if( i != b.back() ) b.push_back(i);
}
cout << b.size() << "\n";
for( auto i : b ) cout << i;
}
L1-6 加密通信
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
string s;
cin >> n >> k >> s;
vector<int> key(26);
for (auto &i: key) cin >> i;
k %= n , k = n - k;
for (int i = k; i < n; i++)
cout << key[s[i] - 'a'];
for (int i = 0; i < k; i++)
cout << key[s[i] - 'a'];
}
L1-7 字符操作
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
string s , v[2];
int a = 0 , b = 1;
cin >> n >> s;
v[0] = s.substr(0,n) , v[1] = s.substr(n,n);
int m; cin >> m;
for( int op , x , y , p , q ; m ; m -- ){
cin >> op >> x >> y;
if( op == 2 ) swap( a , b );
else {
x -= 1 , y -= 1;
if( x < n ) p = a;
else p = b , x -= n;
if( y < n ) q = a;
else q = b , y -= n;
swap( v[p][x] , v[q][y] );
}
}
cout << v[a] << v[b];
}
L1-8 vivo50!
#include <bits/stdc++.h>
using namespace std;
struct Stu{
string name;
double gpa , all;
int de , zhi;
Stu( string name , int gpa , int de , int zhi )
:name(name) , gpa(gpa) , de(de) , zhi(zhi){
all = double( gpa + zhi ) * 0.7 + 0.3 * de;
}
bool operator < ( Stu b ){
if( all != b.all ) return all > b.all;
return name < b.name;
}
};
int main() {
int n , k;
cin >> n >> k;
vector<Stu> s;
string name;
double gpa;
int de , zhi;
for( int i = 1 , g ; i <= n ; i ++ ){
cin >> name >> gpa >> de >> zhi >> g;
if( g == 0 ) continue;
s.emplace_back( name , gpa * 10 + 50 , min( de + 70 , 100 ) , zhi );
}
sort( s.begin(), s.end() );
for( int i = 0 , rk ; i < s.size() ; i ++ ){
if( i != 0 && s[i].all == s[i-1].all ) rk = rk;
else rk = i + 1;
if( rk > k ) break;
cout << rk << " " << s[i].name;
printf(" %.1lf\n" , s[i].all );
}
}
L2-1 游戏圈
就用并查集维护一下就好了
#include <bits/stdc++.h>
using namespace std;
class dsu{
private:
vector<int> fa;
public:
dsu( int n = 1 ){
fa = vector<int>( n+1 , -1 ) , fa[0] = 0;
}
int getfa( int x ){
if( fa[x] < 0 ) return x;
return fa[x] = getfa( fa[x] );
}
void merge( int x , int y ){
x = getfa(x) , y = getfa(y);
if( x == y ) return ;
if( fa[x] > fa[y] ) swap( x , y );
fa[x] += fa[y] , fa[y] = x;
}
bool check( int x , int y ){
x = getfa(x) , y = getfa(y);
return ( x == y );
}
};
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read() , m = read() , q = read();
dsu t(n);
for( int u , v ; m ; m -- ){
u = read() , v = read();
t.merge( u , v );
}
for( int x , y ; q ; q -- ){
x = read() , y = read();
if( t.check(x,y) ) printf("yes\n");
else printf("no\n");
}
int cnt = 0;
for( int i = 1 ; i <= n ; i ++ ){
if( t.getfa(i) == i ) cnt ++;
}
cout << cnt << "\n";
}
如果不会并查集的话当然也可以用搜索搞一搞
#include<bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read() , m = read() , q = read() , cnt = 0;
vector<vector<int>> e(n+1);
for( int a , b ; m ; m -- )
a = read() , b = read() , e[a].push_back(b) , e[b].push_back(a);
vector<int> vis( n+1 );
for( int i = 1 ; i <= n ; i ++ ){
if( vis[i] ) continue;
cnt ++;
queue<int> q;
q.push(i);
while( !q.empty() ){
int u = q.front(); q.pop();
if( vis[u] ) continue;
vis[u] = i;
for( auto v : e[u] ){
if( vis[v] ) continue;
q.push(v);
}
}
}
for( int a , b ; q ; q -- ){
a = read() , b = read();
if( vis[a] != vis[b] ) printf("no\n");
else printf("yes\n");
}
printf("%d\n" , cnt );
return 0;
}
L2-2 组套题
模拟题,没什么算法,注意细节就好了。然后就是如何处理读入和输入可以采用格式化的形式,比较方便。
#include <bits/stdc++.h>
using namespace std;
int32_t main() {
int n;
scanf("%d" , &n );
vector<int> a(11);
for (int i = 1; i <= 10; i++) scanf("%d" , &a[i] );
vector<tuple<int, int, int> > v;
vector<queue<pair<int, int>>> q(11);
for (int m, id = 1; id <= n; id++) {
scanf("%d" , &m);
for ( int x , y ; m; m--) {
scanf(" T%d-%d" , &x ,&y );
if (a[x] > 0) a[x]--, v.emplace_back(x, id, y);
else q[x].emplace(id, y);
}
getchar();
}
for (int i = 1; i <= 10; i++) {
if (a[i] == 0) continue;
for (int j = i + 1; a[i] && j <= 10; j++) {
while (!q[j].empty() && a[i])
a[i]--, v.emplace_back(j, q[j].front().first, q[j].front().second), q[j].pop();
}
for (int j = i - 1; a[i] && j >= 1; j--) {
while (!q[j].empty() && a[i])
a[i]--, v.emplace_back(j, q[j].front().first, q[j].front().second), q[j].pop();
}
}
sort(v.begin(), v.end());
for( auto it : v )
printf("%d-%d%c" , get<1>(it) , get<2>(it) , " \n"[it==v.back()]);
return 0;
}
L2-3 简单的数数
比较典的 dp题,\(f[i][j]\)表示前\(i\)个数够成\(j\)的方案数
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
const int mod = 998244353;
int main() {
int n = read();
vector<array<int, 10> > f(n + 1);;
for (int i = 1, x; i <= n; i++) {
x = read();
if (i == 1) {
f[i][x] = 1;
continue;
}
for (int j = 0; j < 10; j++) {
if (f[i - 1][j]) {
f[i][(j + x) % 10] = (f[i][(j + x) % 10] + f[i - 1][j]) % mod;
f[i][(j * x) % 10] = (f[i][(j * x) % 10] + f[i - 1][j]) % mod;
}
}
}
for (int i = 0; i <= 9; i++)
cout << f[n][i] << "\n";
return 0;
}
L2-4 回家日
首先,是我赛时的做法,就是按照解封的顺序把点加入到图中,如果这个点通过一条边直接相连的点也已经解封就把边也加入进来,然后用并查集动态的维护联通性,每次更新完一个点就把逐个判断剩余的点中是否有和\(k\)联通的点
#include <bits/stdc++.h>
using namespace std;
class dsu {
private:
vector<int> fa;
public:
dsu(int n = 1) {
fa = vector<int>(n + 1, -1), fa[0] = 0;
}
int getfa(int x) {
if (fa[x] < 0) return x;
return fa[x] = getfa(fa[x]);
}
void merge(int x, int y) {
x = getfa(x), y = getfa(y);
if (x == y) return;
if (fa[x] > fa[y]) swap(x, y);
fa[x] += fa[y], fa[y] = x;
}
bool check(int x, int y) {
x = getfa(x), y = getfa(y);
return (x == y);
}
};
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int main() {
int n = read(), m = read(), k = read();
dsu d(n);
vector<int> a(n + 1), p(n + 1, -1);
for (int i = 1; i <= n; i++) a[i] = read();
vector<vector<int>> e(n + 1, vector<int>());
for (int u, v; m; m--)
u = read(), v = read(), e[u].push_back(v), e[v].push_back(u);
int t = 1;
for (; t <= n; t++) {
p[a[t]] = 0;
for (auto v: e[a[t]]) {
if (p[v] == 0) d.merge(v, a[t]);
}
if (a[t] == k) break;
}
unordered_set<int> st;
for (int i = 1; i <= n; i++) {
if (p[i] == 0 && d.check(i, k) == true) p[i] = t;
else st.emplace(i);
}
t ++;
for (; t <= n; t++){
p[ a[t] ] = 0;
for (auto v: e[a[t]]) {
if (p[v] >= 0) d.merge(v, a[t]);
}
vector<int> cur;
for( auto j : st )
if( p[j] == 0 && d.check( j , k ) == true )
p[j] = t , cur.push_back(j);
for( auto j : cur )
st.erase(j);
}
for( int i = 1 ; i <= n ; i ++ )
printf("%d%c" , p[i] , (" \n"[i==n]));
return 0;
}
然后正确实际上,我们可以用 bfs 的方式来维护这张图\(dis[i]\)表示\(i\)到\(k\)路径上的最大值,从起点开始搜索就好了。
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read(), m = read(), sta = read();
vector<int> a(n + 1);
for (int i = 1 , x ; i <= n; i++) x = read() , a[x] = i ;
vector<vector<int>> e(n + 1);
for (int u, v; m; m--)
u = read(), v = read(), e[u].push_back(v), e[v].push_back(u);
vector<int>dis(n + 1, INT_MAX);
dis[sta] = a[sta];
queue<int> q;
q.emplace(sta);
while (!q.empty()) {
auto u = q.front(); q.pop();
for (auto v: e[u]) {
if( dis[v] <= max( a[v] , dis[u] ) ) continue;
dis[v] = max( a[v] , dis[u] ) , q.emplace( v );
}
}
for( int i = 1 ; i <= n ; i ++ )
printf("%d%c" , dis[i] , " \n"[i==n] );
return 0;
}
然后可以优化这个搜索过程,通过优先队列优化搜索顺序,并且保证每个点只扩展一次。
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
int32_t main() {
int n = read(), m = read(), sta = read();
vector<int> a(n + 1);
for (int i = 1 , x ; i <= n; i++) x = read() , a[x] = i ;
vector<vector<int>> e(n + 1);
for (int u, v; m; m--)
u = read(), v = read(), e[u].push_back(v), e[v].push_back(u);
vector<int>dis(n + 1, INT_MAX);
dis[sta] = a[sta];
queue<int> q;
q.emplace(sta);
while (!q.empty()) {
auto u = q.front(); q.pop();
for (auto v: e[u]) {
if( dis[v] <= max( a[v] , dis[u] ) ) continue;
dis[v] = max( a[v] , dis[u] ) , q.emplace( v );
}
}
for( int i = 1 ; i <= n ; i ++ )
printf("%d%c" , dis[i] , " \n"[i==n] );
return 0;
}