AcWing:第74场周赛

99 阅读3分钟

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

AcWing——第74场周赛

4707. 最小身高差 - AcWing题库

问题解析

为了方便,可以把第n+1个位置设置成a[1]。

这样计算最小身高差时,只有从1到n计算:mn=min(mn,abs(f[i]-f[i+1]));

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
​
int a[N];
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    a[n + 1] = a[1];
    int mn = 1e9;
    for (int i = 1; i <= n; i++)
    {
        mn = min(mn, abs(a[i] - a[i + 1]));
    }
    cout << mn;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}

4708. 立方体 - AcWing题库

问题解析

三维空间走迷宫。

用三维数组存下迷宫,以(1,x,y)为起点开始bfs。

因为是三维的,所以方向一共有(0,1,0),(0,-1,0),(0,0,1),(0,0,-1),(1,0,0),(-1,0,0)等六种。

剩下的就和普通的bfs一样。

注意要记录走过的节点,防止重复bfs。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
​
char f[20][20][20];
bool st[20][20][20];
int dk[6] = { 0,0,0,0,1,-1 }, dx[6] = { 1,0,-1,0,0,0 }, dy[6] = { 0,1,0,-1,0,0 };
void solve()
{
    int k, n, m, x, y, z;
    cin >> k >> n >> m;
    for (int i = 1; i <= k; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            for (int l = 1; l <= m; l++)
            {
                cin >> f[i][j][l];
            }
        }
    }
    cin >> x >> y;
    queue < pair<int, pair<int, int>>>que;
    que.push({ 1,{x,y} });
    st[1][x][y] = true;
    int cnt = 1;
    while (!que.empty())
    {
        int len = que.size();
        for (int i = 0; i < len; i++)
        {
            z = que.front().first, x = que.front().second.first, y = que.front().second.second;
            que.pop();
            for (int j = 0; j < 6; j++)
            {
                int a = z + dk[j], b = x + dx[j], c = y + dy[j];
                if (a >= 1 && a <= k && b >= 1 && b <= n && c >= 1 && c <= m && f[a][b][c] == '.' && !st[a][b][c])
                {
                    cnt++;
                    que.push({ a,{b,c} });
                    st[a][b][c] = true;
                }
            }
        }
    }
    cout << cnt;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}

4709. 三元组 - AcWing题库

问题解析

对于三元组问题,我们可以想一下二元组问题的解法。

如果是二元组,就是要求i<j,且a[i]>a[j] 的对数。这就是类似计算逆序对。

对于计算二元组的情况,我们可以用线段树来做到:对于a[j],我们计算a[j]+1~mx的区间和,这就是a[i]>a[j]的对数,然后线段树上a[j]处的值++(记录a[j]的出现次数)。

如果我们知道了a[i]>a[j]的对数,那么只要看有多少对a[j]>a[k],我们就可以得出三元组a[i]>a[j]>a[k]的对数了。

所以我们用第一次二元组a[i]>a[j]的结果建下第二个线段树,用同样的方法计算a[j]>a[k]的对数即可。

AC代码(复杂度没问题,但是常数太大)

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
​
int a[N], f[4 * N], f2[4 * N];
void revise(int k, int l, int r, int x, int y, int z)
{
    if (l == r)
    {
        if (z == 1)
            f[k] += y;
        else
            f2[k] += y;
        return;
    }
    int m = (l + r) / 2;
    if (x <= m)revise(k + k, l, m, x, y, z);
    else revise(k + k + 1, m + 1, r, x, y, z);
    f[k] = f[k + k] + f[k + k + 1];
    f2[k] = f2[k + k] + f2[k + k + 1];
}
int calc(int k, int l, int r, int x, int y, int z)
{
    if (l == x && r == y)
        if (z == 1)return f[k];
        else return f2[k];
    int m = (l + r) / 2;
    if (y <= m)return calc(k + k, l, m, x, y, z);
    else
        if (x > m)return calc(k + k + 1, m + 1, r, x, y, z);
        else return (calc(k + k, l, m, x, m, z) + calc(k + k + 1, m + 1, r, m + 1, y, z));
}
​
void solve()
{
    int n;
    cin >> n;
    vector<int>v(n);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        v[i - 1] = a[i];
    }
    sort(v.begin(), v.end());
    int cnt = 1;
    unordered_map<int, int>mymap;
    for (auto i : v)
    {
        if (!mymap.count(i))
        {
            mymap[i] = cnt++;
        }
    }
    int res = 0;
    for (int i = 1; i <= n; i++)
    {
        res += calc(1, 1, cnt, mymap[a[i]] + 1, cnt, 2);
        int x = calc(1, 1, cnt, mymap[a[i]] + 1, cnt, 1);
        revise(1, 1, cnt, mymap[a[i]], 1, 1);
        revise(1, 1, cnt, mymap[a[i]], x, 2);
    }
    cout << res;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}