AcWing:第55场周赛

68 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

AcWing——第55场周赛

竞赛 - AcWing

4479. 最长子序列 - AcWing题库

给定一个长度为 n 的序列 a1,a2,…,an 和一个长度为 m 的序列 b1,b2,…,bm。

现在,我们希望找到一个序列 a 的子序列,使得该子序列满足:

子序列中的每一个元素都在序列 b 中出现过。 子序列的长度应尽可能长。 请你输出满足条件的最长子序列。

输入格式

第一行包含两个整数 n,m。

第二行包含 n 个整数 a1,a2,…,an。

第三行包含 m 个整数 b1,b2,…,bm。

输出格式

在一行中输出满足条件的最长子序列。

如果满足条件的最长子序列为空,则不输出任何内容或输出单个换行符均可。

数据范围

所有测试点满足 1≤n,m≤10,0≤ai,bi≤9。

输入样例1:

7 3
3 5 7 1 6 2 8
1 2 7

输出样例1:

7 1 2

问题解析

题目要求输出的是“序列”,直接遍历一遍a数组,如果a[i]在b[i]出现过了那就把这个元素输出即可。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
​
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<int>a(n), b(m);
    unordered_map<int, int>mymap;
    for (int i = 0; i < n; i++)cin >> a[i];
    for (int i = 0; i < m; i++)
    {
        cin >> b[i];
        mymap[b[i]] = 1;
    }
    for (int i = 0; i < n; i++)
    {
        if (mymap[a[i]])cout << a[i] << " ";
    }
    return 0;
}

4480. 倒垃圾 - AcWing题库

一条街道可以看作一个数轴。

街道上住着 n 个居民并设有 m 个垃圾桶,每个居民的住所或垃圾桶占据一个位置。

已知,这 n+m 个位置两两不同。

每个居民每天都会前往距离自己家最近的垃圾桶处倒垃圾。

如果这样的垃圾桶不唯一,则居民会优先选择前往位置坐标更小的垃圾桶处倒垃圾。

请你计算,对于每个垃圾桶,每天有多少居民在该垃圾桶处倒垃圾。

输入格式

第一行包含两个整数 n,m。

第二行包含 n+m 个整数 x1,x2,…,xn+m,表示所有居民住所以及垃圾桶的位置坐标。

第三行包含 n+m 个整数 t1,t2,…,tn+m,如果 ti=1,则表示第 i 个位置坐标处是垃圾桶,如果 ti=0,则表示第 i 个位置坐标处是居民住所。

输入保证,满足 ti=1 的 i 的数量为 m。

输出格式

不妨按照位置坐标从小到大的顺序,将 m 个垃圾桶编号 1∼m。

请你在一行中输出 m 个整数 a1,a2,…,am,其中 ai 表示每天在第 i 个垃圾桶处倒垃圾的居民数量。

数据范围

前三个测试点满足 1≤n,m≤5。 所有测试点满足 1≤n,m≤10^5,1≤x1<x2<…<xn+m≤10^9,0≤ti≤1。

输入样例1:

3 1
1 2 3 10
0 0 1 0

输出样例1:

3

输入样例2:

1 4
2 4 6 10 15
1 1 1 1 0

输出样例2:

0 0 0 1

问题解析

滑动窗口做法。

先把所有的垃圾桶存入一个数组ans里,如果只有一个垃圾桶,直接输出n的值即可,因为所有的垃圾都只能扔到那里。

我们用双指针l、r来指向垃圾桶的位置,遍历所有的住户,如果当前住户的位置在我们双指针指向的位置之间,那我们就通过计算判断这个住户是去l扔好还是r好(如果相等,也是去l扔),并记录下来,当住户的位置大于我们的r指针,那就把窗口右移(l指向原来的r,r往下走一位,如果r就是最后一个垃圾桶了,就只移动左指针),因为住户位置如果大于r了,那么相对于到l的距离,住户肯定是到r的距离更小。最后输出所有记录的数量即可。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
​
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<int>a(n + m), b(m + n), ans;
    unordered_map<int, int>mymap,cnt;
    if (m == 1)
    {
        cout << n << endl;
        return 0;
    }
    for (int i = 0; i < n+m; i++)cin >> a[i];
    for (int i = 0; i < n+m; i++)
    {
        cin >> b[i];
        if (b[i] == 1)ans.push_back(a[i]), mymap[a[i]] = 1;
    }
    int l = 0, r = 1;
    for (int i = 0; i < n+m; i++)
    {
        if (a[i] > ans[r])
        {
            l = r;
            if (r + 1 < m)r++;
        }
        if (mymap[a[i]] == 0)
        {
            if (abs(a[i] - ans[l]) <= abs(a[i] - ans[r]))
            {
                cnt[ans[l]]++;
            }
            else
            {
                cnt[ans[r]]++;
            }
        }
    }
    for (int i = 0; i < m; i++)cout << cnt[ans[i]] << " ";
    
    return 0;
}

4481. 方格探索 - AcWing题库

给定一个 n 行 m 列的方格矩阵。行坐标从上到下为 1∼n,列坐标从左到右为 1∼m。

其中的每个方格,要么是空格(用 . 表示),要么包含障碍物(用 * 表示)。

初始时,一个人位于第 r 行第 c 列的空格之中。

他可以沿上下左右四个方向进行移动,每次移动一格距离。

对于他的移动,有如下限制:

他不能进入到包含障碍物的方格中,也不能走出矩阵的边界。 在整个移动过程中,他向左移动的总次数不能超过 x 次。 在整个移动过程中,他向右移动的总次数不能超过 y 次。 请问,一共有多少个空格是此人可以抵达的?

注意,初始空格视为此人可达。

输入格式

第一行包含两个整数 n,m。

第二行包含两个整数 r,c。

第三行包含两个整数 x,y。

接下来 n 行,每行包含一个长度为 m 的由 . 和 * 组成的字符串,用来描述方格矩阵。

输入保证第 r 行第 c 列的方格一定是空格。

输出格式

一个整数,表示可达空格数量。

数据范围

前三个测试点满足 1≤n,m≤5。 所有测试点满足 1≤n,m≤2000,1≤r≤n,1≤c≤m,0≤x,y≤10^9。

输入样例:

4 5
3 2
1 2
.....
.***.
...**
*....

输出样例:

10

问题解析

走迷宫问题,只是这里还要记录你当前向左或向右走了多少步。

队列要自己做个自定义数据类型,要能存下四个变量:{横坐标,纵坐标,已经向左走的次数,已经向右走的次数},然后就是标准的走迷宫,只是每次向左走和向右走的时候对应的变量要+1,如果次数大于了限制次数,那就走不到这一格。

走到一格后我们要打两个标记,一个是判断这个格子之前有没有走过,如果没有就打上标记,并且计数器++;另一个是记录走到这个格子时已经向左或向右走了几次,如果想要走到更远的地方,那么肯定是向左向右走的次数少才行,如果后面再次到达这个格子,向左向右走的次数大于我们之前记录过的就跳过,如果小于就更换标记,并且把这个点入队。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
PII cnt[2050][2050];
int mymap[2050][2050];
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
​
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m, x, y, a, b, res = 1;
    cin >> n >> m >> x >> y >> a >> b;
    vector<string>v(n);
    for (int i = 0; i < n; i++)
        cin >> v[i];
    queue<pair<pair<int, int>, pair<int, int>>>que;
​
    que.push({ {x - 1,y - 1} ,{0,0} });
    mymap[x - 1][y - 1] = 1;
    while (!que.empty())
    {
        int len = que.size();
        for (int i = 0; i < len; i++)
        {
            pair<pair<int, int>, pair<int, int>> t = que.front();
            que.pop();
            int l = t.second.first, r = t.second.second;
            for (int j = 0; j < 4; j++)
            {
                int c = l + (j == 3), d = r + (j == 1);
                if (c > a || d > b)continue;
                int x1 = t.first.first + dx[j], y1 = t.first.second + dy[j];
                if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && v[x1][y1] == '.')
                {
                    if (mymap[x1][y1] && cnt[x1][y1].first <= c && cnt[x1][y1].second <= d)continue;
                    if (mymap[x1][y1] == 0)
                    {
                        mymap[x1][y1] = 1;
                        res++;
                    }
                    cnt[x1][y1] = { c,d };
                    que.push({ {x1,y1},{c,d} });
                }
​
            }
        }
    }
​
​
    cout << res << endl;
​
    return 0;
}