持续创作,加速成长!这是我参与「掘金日新计划 · 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;
}