2022“杭电杯”中国大学生算法设计超级联赛(3)
[题目链接](Search Result (hdu.edu.cn))
C Cyber Language
题目大意
一个字符串,把它的每个单词的首字母大写输出。
题解
见代码。
代码
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 2e2 + 5;
int t;
char a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
cin.ignore();
while (t--)
{
cin.getline(a, maxn);
for (int i = 0; i < strlen(a); i++)
{
if (i == 0 || a[i - 1] == ' ')
cout << char(toupper(a[i]));
}
cout << endl;
}
return 0;
}
I Package Delivery
题目大意
一个人有n个快递,每个快递被取的时间区间为[li,ri],每次最多可以拿k个快递,问最少需要取几次。
题解
贪心算法,每次考虑未取走的所有快递中 r 最小的那一天(此时不得不取),把所有l小于等于当前r且未取走的快递加入优先级队列,因为这些快递都可以取了,并按r大小排序,即先取走r较小的快递。
代码
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 5;
int t, n, k, res;
int ql[maxn], qr[maxn];
P p[maxn];
bool vis[maxn];
bool cmpl(const int &a, const int &b)
{
return p[a].first < p[b].first;
}
bool cmpr(const int &a, const int &b)
{
return p[a].second < p[b].second;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
memset(vis, 0, sizeof vis);
priority_queue<P, vector<P>, greater<P>> q;
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> p[i].first >> p[i].second;
ql[i] = qr[i] = i;
}
sort(ql + 1, ql + 1 + n, cmpl);
sort(qr + 1, qr + 1 + n, cmpr);
res = 0;
for (int i = 1, j = 1; i <= n; i++)
{
if (vis[qr[i]])
continue;
while (j <= n && p[ql[j]].first <= p[qr[i]].second)
{
q.push(P(p[ql[j]].second, ql[j]));
j++;
}
for (int l = 1; l <= k; l++)
{
if (q.empty())
break;
vis[q.top().second] = 1;
q.pop();
}
res++;
}
cout << res << endl;
}
}
L Two Permutations
题目大意
有两个长度为n的排列P和Q,一个长为2n的序列R,判断有几种方式可以使P和Q组成R,没有则为零。
题解
动态规划,设 f(i,j)表示 P 的前 i 项匹配上了 S,且 Pi 匹配 S 中数字 Pi 第 j 次出现的位置时,有多少种合法的方案。
转移时枚举 Pi+1 匹配哪个位置,那么 Pi 匹配的位置与 Pi+1 匹配的位置中间的那段连续子串需要完全匹配 Q 中对应的子串,使用字符串 Hash 进行判断是否相等。
注意要特判序列 R 中每个数字出现次数不都为 2 的情况,此时答案为 0。
dp:
初始化:此时Q的1,x-1和R的1,x-1需要匹配(x代表P1在R中的位置)。
if (checked(1, x - 1, 1, x - 1))
dp[1][i] = 1;
递推:此时Q的x-i+1,y-i-1和R的x+1,y-1需要匹配(x代表Pi在R中的位置,y代表Pi+1在R中的位置)。
if (checked(x - i + 1, y - i - 1, x + 1, y - 1))
dp[i + 1][k] = (dp[i + 1][k] + dp[i][j]) % mod;
结尾:此时Q的x-n+1,n和R的x+1,n*2需要匹配(x代表Pn在R中的位置)。
if (checked(x - n + 1, n, x + 1, n * 2))
res = (res + dp[n][j]) % mod;
代码
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> P;
const int maxn = 3e5 + 5;
const int S = 233;
const int mod = 998244353;
int t, n, res;
bool ok;
int a[maxn], b[maxn], c[maxn * 2], dp[maxn][2], lc[maxn][2];
ull pb[maxn], pc[maxn * 2], p[maxn * 2];
ull ju(ull *f, int x, int y)
{
return f[y] - f[x - 1] * p[y - x + 1];
}
bool checked(int bl, int br, int cl, int cr)
{
if (bl > br)
return 1;
if (bl < 1 || br > n)
return 0;
return ju(pb, bl, br) == ju(pc, cl, cr);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
p[0] = 1;
for (int i = 1; i < maxn * 2; i++)
p[i] = p[i - 1] * S;
cin >> t;
while (t--)
{
memset(dp, 0, sizeof dp);
memset(lc, 0, sizeof lc);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
{
cin >> b[i];
pb[i] = pb[i - 1] * S + b[i];
}
for (int i = 1; i <= n * 2; i++)
{
cin >> c[i];
pc[i] = pc[i - 1] * S + c[i];
if (!lc[c[i]][0])
lc[c[i]][0] = i;
else
lc[c[i]][1] = i;
}
ok = 1;
for (int i = 1; i <= n; i++)
{
if (!lc[i][0] || !lc[i][1])
{
ok = 0;
break;
}
}
if (!ok)
{
cout << 0 << endl;
continue;
}
for (int i = 0; i < 2; i++)
{
int x = lc[a[1]][i];
if (checked(1, x - 1, 1, x - 1))
dp[1][i] = 1;
}
for (int i = 1; i < n; i++)
{
for (int j = 0; j < 2; j++)
{
int x = lc[a[i]][j];
for (int k = 0; k < 2; k++)
{
int y = lc[a[i + 1]][k];
if (y <= x)
continue;
if (checked(x - i + 1, y - i - 1, x + 1, y - 1))
dp[i + 1][k] = (dp[i + 1][k] + dp[i][j]) % mod;
}
}
}
res = 0;
for (int j = 0; j < 2; j++)
{
int x = lc[a[n]][j];
if (checked(x - n + 1, n, x + 1, n * 2))
res = (res + dp[n][j]) % mod;
}
cout << res << endl;
}
}
K Taxi
题目大意
有n个城镇,坐标为(xi,yi),现在给一个坐标,求出最大的min(|x′−xk|+|y′−yk|,wk)。
题解
官方题解,很清楚。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
const int Max = 0x3f3f3f3f;
int n, q, t;
struct Node
{
int x, y, w;
bool operator<(const Node &a) const
{
return w < a.w;
}
} node[maxn];
int a[maxn], b[maxn], c[maxn], d[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> node[i].x >> node[i].y >> node[i].w;
sort(node + 1, node + 1 + n);
a[n + 1] = b[n + 1] = c[n + 1] = d[n + 1] = -Max;
for (int i = n; i >= 1; i--)
{
a[i] = max(a[i + 1], -node[i].x - node[i].y);
b[i] = max(b[i + 1], -node[i].x + node[i].y);
c[i] = max(c[i + 1], node[i].x - node[i].y);
d[i] = max(d[i + 1], node[i].x + node[i].y);
}
while (q--)
{
int x, y;
cin >> x >> y;
int l = 1, r = n, mid, temp, res = 0;
while (l <= r)
{
mid = (l + r) >> 1;
temp = x + y + a[mid];
temp = max(temp, x - y + b[mid]);
temp = max(temp, -x + y + c[mid]);
temp = max(temp, -x - y + d[mid]);
if (temp > node[mid].w)
{
l = mid + 1;
res = max(res, node[mid].w);
}
else
{
r = mid - 1;
res = max(res, temp);
}
}
cout << res << endl;
}
}
return 0;
}
B Boss Rush
题目大意
题解
代码