自学内容网 自学内容网

ZISUOJ 2024算法基础公选课练习二

一、前言

先把代码丢上来,后续再补上思路

二、题目总览

ac162b2f392f4cb5bba5db987f3f7bef.png

三、具体题目

3.1 问题 A: 成绩排序1

3135011fc36d4ce4ae746167e43ba568.png

参考代码

简单排序

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int t = 1;
    std::cin >> t;
    while(t--) {
        int n;
        std::cin >> n;
        std::vector<int> v(n);
        for(auto &vi:v) std::cin >> vi;
        std::sort(v.begin(),v.end(),[&](const int &num1,const int &num2) {
            return num1>num2;
        });
        for(int i = 0;i<n;i++) std::cout << v[i] << " \n"[i==n-1];
    }
    
    return 0;
}

3.2 问题 B: 数字和排序

3d1b1eb404f648da997ede216d19cd63.png

参考代码

简单排序

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n = 1;
    while(std::cin >> n) {
        if(n==0) break;
        std::vector<pii> v(n);
        for(int i = 0;i<n;i++) {
            int num;std::cin >> num;
            int tmp = num,sum = 0;
            while(tmp!=0) {
                sum+=tmp%10;
                tmp/=10;
            }
            v.emplace_back(sum,num);
        }
        std::sort(v.begin(),v.end(),[&](const pii& p1,const pii& p2) {
            if(p1.first!=p2.first) return p1.first>p2.first;
            return p1.second > p2.second;
        });
        for(int i = 0;i<n;i++) {
            std::cout << v[i].second << " \n"[i==n-1];
        }

    }
    
    return 0;
}

3.3 问题 C: 帆帆的挂件

e6237a365218498ab6cf1ce16e9b0f27.png

参考代码

简单模拟

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n,x_0;
    std::cin >> n >> x_0;
    std::vector<int> a(n),b(n);
    for(auto &ai:a) std::cin >> ai;
    for(auto &bi:b) std::cin >> bi;
    int ans = 0;
    for(int i = 0;i<n;i++) {
        if(x_0>=a[i]) {
            x_0+=b[i];
            ++ans;
        }
    }
    std::cout << ans << '\n';
    
    return 0;
}

3.4 问题 D: 文件名排序

aa95c4f631f14b6f8481e5829e7ed0be.png

参考代码

stringstream很好处理这种读入情况

#include <bits/stdc++.h>
using i64 = long long;
using pss = std::pair<std::string,std::string>;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    std::string line;
    std::vector<pss> v;
    while(std::getline(std::cin,line)) {
        std::stringstream ss(line);
        std::string tmp1,tmp2;
        while(ss >> tmp1 >> tmp2) v.emplace_back(tmp2,tmp1);
    }
    std::sort(v.begin(),v.end());
    for(const auto &vi:v) {
        std::cout << vi.second << ' ' << vi.first << '\n';
    }
    
    return 0;
}

3.5 问题 E: 火星数排序

2bae9a1544da4ce98b2488b9261fd77b.png

参考代码

可以用哈希表映射过去,写题的时候脑子犯昏,写了好多if

#include <bits/stdc++.h>
using namespace std;
struct number{
int en;
int mn;
}a[1000];

int earth(int n){
int temp=n;
int total = 0;
int sum[20];
int index = 0;
while(temp != 0){
if(temp%10==0){
sum[index] = 0;
}else if(temp%10==8){
sum[index] = 1;
}else if(temp%10==1){
sum[index] = 2;
}else if(temp%10==5){
sum[index] = 3;
}else if(temp%10==2){
sum[index] = 4;
}else if(temp%10==3){
sum[index] = 5;
}else if(temp%10==9){
sum[index] = 6;
}else if(temp%10==4){
sum[index] = 7;
}else if(temp%10==7){
sum[index] = 8;
}else if(temp%10==6){
sum[index] = 9;
}
index++;
temp /= 10;
}
for(int i = index-1;i>=0;i--) total = total*10+sum[i];
return total;
}


bool cmp1(number a,number b){
return a.en<b.en;
}
int main(){
    cin.tie(nullptr)->sync_with_stdio(false);

int Case;
cin>>Case;
for(int i=0;i<Case;i++){
int j=0;
int n;cin >> n;
for(int j = 0;j<n;j++) cin >> a[j].mn;

for(int j = 0;j<n;j++) a[j].en = earth(a[j].mn);
sort(a,a+n,cmp1);

for(int j = 0;j<n;j++){
if(j==0) cout << a[j].mn;
else cout << ' ' << a[j].mn;
}
cout << '\n';
}


return 0;
}

3.6 问题 F: 帆帆的数位计算

fc254ef556cb4911804d7ae33dd2d48b.png

参考代码

写个循环模拟就行,我当时想复杂了

#include <bits/stdc++.h>
using i64 = long long;

void dfs(std::string num,int step) {
    if(num.size()==1) {
        std::cout << step << '\n';
        return;
    }
    int sum = 0;
    for(const auto &c:num) {
        sum+=c^48;
    }
    dfs(std::to_string(sum),step+1);
}
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    std::string num;
    std::cin >> num;
    dfs(num,0);
    
    return 0;
}

3.7 问题 G: 帆帆的数列

a3cbc26be75d4db798b84107f9cded02.png

参考代码

前缀和+贪心

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int t = 1;
    std::cin >> t;
    while(t--) {
        int n,m;
        std::cin >> n;
        std::vector<int> a(n+1,0),preA(n+1,0);
        for(int i = 1;i<=n;i++) {
            std::cin >> a[i];
            preA[i] = preA[i-1]+a[i];
        }
        std::cin >> m;
        std::vector<int> b(m+1,0),preB(m+1,0);
        for(int i = 1;i<=m;i++) {
            std::cin >> b[i];
            preB[i] = preB[i-1]+b[i];
        }

        int ans = 0;
        for(int i = 0;i<=n;i++) {
            for(int j = 0;j<=m;j++) {
                ans = std::max(ans,preA[i]+preB[j]);
            }
        }
        std::cout << ans << '\n';
    }
    
    return 0;
}

3.8 问题 H: 帆帆的糖

dff4f2074e4f45a4978112b343c80389.png

参考代码

一开始当成dfs写了,没看到范围,真是蠢了。可以直接二分枚举答案,不能直接暴力,会TLE

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n,k;
    std::cin >> n >> k;
    int ans = 0;
    int low = 1,high = n;
    
    while(low<high) {
        int mid = (low+high)>>1;
        if(1LL*(1+mid)*mid/2-(n-mid)>=k) {
            high = mid;
        }else {
            low = mid+1;
        }
    }
    std::cout << n-low << '\n';

    return 0;
}

3.9 问题 I: Determine the Photo Position

90509c8110e9494a999386473f63cd7f.png

参考代码

前缀和

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    int n,m;
    std::cin >> n >> m;
    std::vector<std::vector<char>> g(n+5,std::vector<char>(n+5));
    std::vector<std::vector<int>> pre(n+5,std::vector<int>(n+5,0));
    for(int i = 1;i<=n;i++) {
        for(int j = 1;j<=n;j++) {
            std::cin >> g[i][j];
            pre[i][j]=pre[i][j-1]+(g[i][j]^48);
        }
    }

    std::string t;std::cin >> t;

    int ans = 0;
    for(int i = 1;i<=n;i++) {
        for(int j = m;j<=n;j++) {
            if(pre[i][j]-pre[i][j-m]==0) {
                ++ans;
            }
        }
    }
    std::cout << ans << '\n';

    return 0;
}

3.10 问题 J: Ball Dropping

6d3e1820e72f4b03b807428c87d94187.png

参考代码

初中数学计算

#include <bits/stdc++.h>
using i64 = long long;

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    double r,a,b,h;
    std::cin >> r >> a >> b >> h;
    if(2*r<=b) {
        std::cout << "Drop\n";
        return 0;
    }
    double h0 = std::sqrt(h*h+((a-b)/2)*((a-b)/2));
    double sin = ((a-b)/2)/h0;
    double cos = h/h0;
    double tan = ((a-b)/2)/h;
    double x1 = r*sin,x2 = (r*cos-b/2)/tan;

    std::cout << "Stuck\n";
    std::cout << std::fixed << std::setprecision(10) << x1+x2 << '\n';

    return 0;
}

3.11 问题 K: Cut the Tree

c8a12463fc934044acd4f796c3019b0c.png

参考代码

套了别人的两个模板,链式前向星和带权的线段树+dfs找树上LIS,注意数组不能开太大也不能开太小

#include <bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int,int>;
constexpr int N = 1e5+5,M = N,INF = 0x3f3f3f3f;

//链式前向星
int head[N];
int val[N];
int n;
int ans;

struct edge{
int next, to, w;
}e[N << 1];
int cnt;

void init(){
for(int i = 0; i <= n; i++)
head[i] = -1;
cnt = 0;
}

void add(int u, int v, int w = 0){
e[cnt].w = w;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt++;
}

//带权线段树+dfs找LIS
int tot;
struct Tree{
int l, r;
int lis, lds;
}tree[N * 100];
int rt[N];
int sz[N];
int root, maxPart;
int res;
int vis[N];
void getrt(int S, int u, int f){
sz[u] = 1;
int maxx = 0;
for(int i = head[u]; ~i; i = e[i].next){
int v = e[i].to;
if(vis[v] || f == v)
continue;
getrt(S, v, u);
sz[u] += sz[v];
maxx = std::max(maxx, sz[v]);
}
maxx = std::max(maxx, S - sz[u]);
if(maxx < maxPart){
maxPart = maxx;
root = u;
}
}
int build(){
tot++;
tree[tot].l = tree[tot].r = tree[tot].lis = tree[tot].lds = 0;
return tot;
}
void update(int &p, int l, int r, int pos, int vlis, int vlds){
if(p == 0)
p = build();
tree[p].lis = std::max(tree[p].lis, vlis);
tree[p].lds = std::max(tree[p].lds, vlds);
if(l == r)
return ;
int m = (l + r) >> 1;
if(pos <= m)
update(tree[p].l, l, m, pos, vlis, vlds);
else
update(tree[p].r, m+1, r, pos, vlis, vlds);
}
int merge(int p, int q){
if(!p || !q)
return p + q;
tree[p].lis = std::max(tree[p].lis, tree[q].lis);
tree[p].lds = std::max(tree[p].lds, tree[q].lds);
// 最大上升子序列长度
res = std::max(res, std::max(tree[tree[p].l].lis + tree[tree[q].r].lds,
tree[tree[p].r].lds + tree[tree[q].l].lis));
tree[p].l = merge(tree[p].l, tree[q].l);
tree[p].r = merge(tree[p].r, tree[q].r);
return p;
}
pii query(int p, int l, int r, int L, int R){ // L R 询问
if(!p || l > r)
return {0, 0};
if(L <= l && r <= R)
return {tree[p].lis, tree[p].lds};
int m = (l + r) >> 1;
pii ret = {-INF, -INF};
pii tr, tl;
if(L <= m)
tl = query(tree[p].l, l, m, L, R);
if(m < R)
tr = query(tree[p].r, m+1, r, L, R);
ret.first = std::max(tl.first, tr.first);
ret.second = std::max(tl.second, tr.second);
return ret;
}
void dfs(int u, int f){
rt[u] = 0;
for(int i = head[u]; ~i; i = e[i].next){
int v = e[i].to;
if(v == f)
continue;
dfs(v, u);
}
int nlis = 0, nlds = 0;
for(int i = head[u]; ~i; i = e[i].next){
int v = e[i].to;
if(v == f)
continue;
int lis = query(rt[v], 1, n, 1, val[u]-1).first;
int lds = query(rt[v], 1, n, val[u]+1, n).second;
rt[u] = merge(rt[u], rt[v]);
res = std::max(res, lis + 1 + nlds);
res = std::max(res, nlis + 1 + lds);
nlis = std::max(nlis, lis);
nlds = std::max(nlds, lds);
}
update(rt[u], 1, n, val[u], nlis + 1, nlds + 1);
}
void calc(int S, int u){
maxPart = S;
getrt(S, u, 0);
vis[root] = 1;
int maxx = 0, pos = -1;
for(int i = head[root]; ~i; i = e[i].next){
int v = e[i].to;
res = 0;
dfs(v, root);
if(res > maxx){
maxx = res;
pos = v;
}
}
ans = std::min(ans, maxx);
if(pos == -1 || vis[pos])
return ;
calc(sz[pos], pos);
}
void solve(){
std::cin >> n;
init();
for(int i = 1; i < n; i++){
int u, v;
std::cin >> u >> v;
add(u, v);
add(v, u);
}
for(int i = 1; i <= n; i++)
std::cin >> val[i];
ans = INF;
calc(n, 1);
std::cout << ans << '\n';
}

int main(){
std::cin.tie(nullptr)->sync_with_stdio(false);

    int T;
    // std::cin >> T;
    T = 1;
    while(T--){
        solve();
    }

return 0;
}

 

 

 


原文地址:https://blog.csdn.net/Beau_Will/article/details/143662037

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!