2024年1月24日欢乐赛~Happy

A stong9070奇遇记之合并序列

求两个递增序列合并成一个新的的递增序列后,原来的每个元素处在新序列的第几个位置。

数据范围:\(1≤N,M≤10^5\)

分析
两个有序序列合并为一个新的有序序列,可以想到归并排序的合并操作
对于之后的查询可以使用二分。
复杂度:合并 \(O(n+m)\),查询 \(O((n+m)log_2n)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N<<1],b[N<<1];

int main(){
    cin>>n>>m;
    for(int i=1; i<=n+m; i++) cin>>a[i];
    int i=1, j=n+1, p=0;
    while(i<=n && j<=n+m){
        if(a[i] <= a[j]) b[++p] = a[i++];
        else b[++p] = a[j++];
    }
    while(i<=n) b[++p] = a[i++];
    while(j<=n+m)b[++p] = a[j++];
    for(int i=1; i<=n+m; i++){ // >=
        int x = lower_bound(b+1, b+1+p, a[i]) - b;
        cout<<x<<" ";
        if(i==n) cout<<endl;
    }
    return 0;
}

B 最后一块石头的重量

有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出两块最重的石头,然后将它们一起粉碎。假设石头的重量分别为x 和 y,且 x⩽y。那么粉碎的可能结果如下:

  • 如果 x==y,那么两块石头都会被完全粉碎;
  • 如果 x!=y,那么重量为 x的石头将会完全粉碎,而重量为 y 的石头新重量为 y−x。

最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。

数据范围:1⩽n⩽30,1⩽ 石头重量 ⩽1000.

分析
按照要求模拟,每次选择最大的两个石头,使用大顶堆来维护最大值,每次将维护的数据更新后加入堆中,直到堆内元素数量为1。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,x;

int main(){
    priority_queue<int> q; // 大顶堆
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>x; q.push(x);
    }
    while(q.size() > 1){
        int y = q.top(); q.pop();
        int x = q.top(); q.pop();
        if(x!=y) q.push(y-x);
    }
    if(q.size()==0) q.push(0);
    cout<<q.top();
    return 0;
}

C 【基础】探测池塘

寻找出现在至少两个的相邻读数中的最大的深度(相邻指的是一格的周围的八个格子)。

数据范围:数据范围:1⩽n⩽50.

分析
枚举每一个点(i,j) 看其是不是最大深度。
复杂度:\(O(8nm)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=55;
int d[][2] = {-1,-1,-1,0,-1,1,0,-1,0,0,0,1,1,-1,1,0,1,1};
int n,m,g[N][N],ans;

int dfs(int x,int y) {
    int t=0;
    for(int i=0; i<9; i++) {
        int tx=x+d[i][0],ty=y+d[i][1];
        if(tx<1||tx>n||ty<1||ty>m|| g[tx][ty]==0) continue;
        if(g[x][y] == g[tx][ty]) t++;
    }
    return (t>=2) ? g[x][y] : 0;
}
int main() {
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin>>g[i][j];
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            ans = max(ans, dfs(i,j));
    cout<<ans;
    return 0;
}

D 新二叉树

输入一棵二叉树,输出其先序遍历序列。

数据范围:1≤n≤26

分析
先建树,发现数据较小,于是可以利用数据本身作为下标索引
abc ---> tr[a] = {b,c}
左子树:tr[a].l
左子树:tr[a].r

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=300;
int n, st[N];
struct Node{
    char l,r;
}tr[N];

void dfs(char u){
    if(u=='*') return;
    cout<<u;
    dfs(tr[u].l);
    dfs(tr[u].r);
}
int main() {
    cin>>n; char a,b,c;
    for(int i=1; i<=n; i++) {
        cin>>a>>b>>c;
        st[b] = st[c] = 1;
        tr[a] = {b,c};
    }
    for(int i='a'; i<='z'; i++)
        if(!st[i]){ a = i; break; }
    dfs(a);
    return 0;
}

E 买雪糕

用 V 元来给 N 个人买雪糕,每个人都有一个对雪糕的要求 wi,雪糕的价格不能低于这个要求。雪糕店里有 M 种雪糕,每种雪糕的价格是 ai,最多能满足几个人的要求?

数据范围:1⩽V⩽10^9,3⩽N,M⩽100000, 1⩽wi,ai⩽10000

分析
思考一个策略,使得尽量多的人被满足
要求越低的人越容易被满足,先满足要求低的人
如果当前要求低的人都无法满足,那么要求高的人也一定无法满足。
对元素wi, ai分别升序排序后,利用双指针去匹配合适的物品,如果匹配不到那就无法满足。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,v,w[N],a[N];

int main() {
    cin>>n>>m>>v;
    for(int i=1; i<=n; i++) cin>>w[i];
    for(int i=1; i<=m; i++) cin>>a[i];
    sort(w+1, w+1+n);
    sort(a+1, a+1+m);
    int ans=0;
    for(int i=1, j=1; i<=n; i++) {
        while(j<=m && w[i] > a[j]) j++;
        if(j<=m && v >= a[j]) v-=a[j++], ans ++;
    }
    cout<<ans;
    return 0;
}

F stong9070奇遇记之叫号

有 N 个人去排队叫号,他们编号分别为 1 到 N,每个人手上都有一张其他人的号码 Ai。初始时,所有人没有被叫过。如果第 i 个人没有被叫过,他就叫自己手上的号码 Ai。

问整个叫号结束后,有多少人没有叫过,按升序输出结果。

数据范围:2≤N≤2×10^5, 1≤Ai≤N, Ai!=i.

分析
如过没有被叫过,才会叫手上的号码,考虑使用标记思想,如果某人被叫,就标记。
map<int,int> mp; 申请出战
mp[a[i]]=1; 表示 a[i] 被叫过
mp.count(i)==0; 表示 i 没有被叫过

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,a[N];
map<int,int> mp;
int main() {
    cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];
    for(int i=1; i<=n; i++)
        if(mp.count(i) == 0) mp[a[i]] = 1;
    int ans=0;
    for(int i=1; i<=n; i++)
        if(mp.count(i)==0) ans++;
    cout<<ans<<endl;
    for(int i=1; i<=n; i++)
        if(mp.count(i)==0) cout<<i<<" ";
    return 0;
}
posted @ 2024-01-30 17:31  HelloHeBin  阅读(29)  评论(0编辑  收藏  举报