2024-12-19【Educational Codeforces Round 119 (Rated for Div

61 阅读6分钟

在平面上绘制一个矩形,其对角位于 (0,0) 和 (w,h) 且边与轴平行。

给定一个格点列表,每个点都位于矩形的一侧,但不在其角上。此外,矩形的每一边至少有两个点。

你的任务是以这样的方式选择三个点:

它们中的两个正好属于矩形的同一边;

由它们形成的三角形的面积是最大的。

打印这个三角形的两倍面积。可以证明,任何由格点组成的三角形的两倍面积总是一个整数。

输入

第一行包含一个整数 t (1≤t≤104)——测试用例的数量。

每个测试用例的第一行包含两个整数 w 和 h (3≤w,h≤106)——矩形角的坐标。

接下来的两行包含对两个水平边上的点的描述。首先,一个整数 k (2≤k≤2⋅105)——点数。然后,k 个整数 x1<x2<⋯<xk (0<xi<w) — 按升序排列的点的 x 坐标。第一行的 y 坐标为 0,第二行的 y 坐标为 h。

接下来的两行包含对两个垂直边上的点的描述。首先,一个整数 k (2≤k≤2⋅105)——点数。然后,k 个整数 y1<y2<⋯<yk (0<yi<h)——点的 y 坐标按升序排列。第一行的 x 坐标为 0,第二行的 x 坐标为 w。

所有测试用例中所有边的总点数不超过 2⋅105。

输出

对于每个测试用例,打印一个整数——由三个点形成的三角形的最大面积的两倍,其中三个点恰好属于同一边。

code:


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

typedef pair<int,int> pii;

const int maxn=1e6+5;

void solve(){

int x, y;

cin >> x >> y;

ll maxx = 0;

ll maxy = 0;

for (int i = 0; i < 2;i++){

int n;

cin>>n;

ll a,b;

ll x;

for (int j = 0; j < n; j++){

cin>>x;

if(j==0)a=x;

if(j==n-1)b=x ;

}

maxx = max(maxx, (b-a));

}

for (int i = 0; i < 2;i++){

int n;

cin>>n;

ll a,b;

ll x;

for (int j = 0; j < n; j++){

cin>>x;

if(j==0)a=x;

if(j==n-1)b=x ;

}

maxy = max(maxy, (b-a));

}

ll num = max(maxx * y, maxy * x);

cout << num << endl;

}

int main(){

ios::sync_with_stdio(0);

int t;

cin >> t ;

while(t--){

solve();

}

return 0;

}

C. BA-String

===============================================================================

题目描述


给定一个整数 k 和一个仅由字符“a”(小写拉丁字母)和“*”(星号)组成的字符串 s。

每个星号应替换为几个(从 0 到 k 包括在内)小写拉丁字母“b”。不同的星号可以替换为不同数量的字母“b”。

替换的结果称为 BA 字符串。

如果两个字符串 a 和 b 具有不同的长度或存在这样的位置 i 使得 ai≠bi,则它们是不同的。

当且仅当以下条件之一成立时,字符串 a 在字典序上小于字符串 b:

  • a是b的前缀,但a≠b;

  • 在 a 和 b 不同的第一个位置,字符串 a 有一个字母在字母表中比 b 中的相应字母出现得更早。

现在考虑所有不同的 BA 字符串并找到其中第 x 个字典序最小的字符串

输入

第一行包含一个整数 t (1≤t≤2000)——测试用例的数量。

每个测试用例的第一行包含三个整数 n 、 k n、k n、k 和 x ( 1 ≤ n ≤ 2000 ; 0 ≤ k ≤ 2000 ; 1 ≤ x ≤ 1 0 18 ) x(1≤n≤2000;0≤k≤2000;1≤x≤10^{18}) x(1≤n≤2000;0≤k≤2000;1≤x≤1018)。 n 是字符串 s 的长度。

每个测试用例的第二行是一个字符串 s。它由 n 个字符组成,每个字符都是“a”(小写拉丁字母)或“*”(星号)。

所有测试用例的 n 总和不超过 2000。对于每个测试用例,x 不超过不同 BA 字符串的总数。字符串 s 至少包含一个字符 ‘a’。

输出

对于每个测试用例,打印一个字符串,只包含字符 ‘b’ 和 ‘a’(小写拉丁字母)——第 x 个字典序最小的 BA 字符串。

code:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

typedef pair<int, int> pii;

const int maxn = 1e6 + 5;

void solve()

{

ll n, k, x;

cin >> n >> k >> x;

string s;

cin >> s;

if (x == 1 || k == 0)

{

string ans = "";

for (int i = 0; i < n;i++)

{

if (s[i] == 'a')

{

ans.push_back('a');

}

}

cout << ans << endl;

return;

}

vector v;

for (int i = n - 1; i >= 0; i--)

{

if (s[i] == '*')

{

if (i < (n - 1) && s[i + 1] == '*')

{

v.back() += k;

}

else

{

v.push_back(k + 1);

}

}

}

int m = v.size();

ll s1 = 1;

vector cnt(m, 0);

int i = 0;

for (; i < m; i++)

{

double dx = v[i];

double nn = (x / dx);

if (nn <= s1)

{

for (int j = i; j >= 0; j--)

{

if (j != i)

s1 = s1 / v[j];

cnt[m - j - 1] = (x - 1) / s1;

x = (x - 1) % s1 + 1;

}

break;

}

s1 = s1 * v[i];

}

int inn = m - 1;

char prev = 'a';

string z = "";

for (int i = n - 1; i >= 0; i--)

{

if (s[i] == '' && prev == '')

{

s.erase(s.begin() + i);

continue;

}

else if (s[i] == '*')

{

z = "";

while (cnt[inn]--)

{

z.push_back('b');

}

s.erase(s.begin() + i);

s.insert(i, z);

inn--;

prev = '*';

}

else

{

prev = 'a';

}

}

cout << s << endl;

}

int main()

{

ios::sync_with_stdio(0);

int t;

cin >> t;

while (t--)

{

solve();

}

return 0;

}

D. Exact Change

==================================================================================

题目描述


一天,一大早,你决定在附近的商店给自己买一袋薯条。这家商店有n种不同口味的薯条。一袋第 i 种口味的价格为 a i a_i ai​ burles。

这家商店的一些口味可能会用完,所以你到了那里再决定买哪一种。但是这个计划有两个主要缺陷:

你只有 1、2 和 3 个 burles 的硬币;

由于现在是早上,商店会要求您支付确切的零钱,即。 e.如果你选择第 i 种口味,你将不得不支付完全 a i a_i ai​ burles。

硬币很重,因此您希望总共拿走尽可能少的硬币。这就是为什么您想知道:您应该随身携带的最少硬币总数是多少,以便您可以零钱购买一袋任何口味的薯片?

输入

第一行包含一个整数 t (1≤t≤1000)——测试用例的数量。

每个测试用例的第一行包含单个整数 n (1≤n≤100)——商店中口味的数量。

每个测试用例的第二行包含 n 个整数 a 1 , a 2 , … , a n ( 1 ≤ a i ≤ 1 0 9 ) a_1,a_2,…,a_n (1≤a_i≤10^9) a1​,a2​,…,an​(1≤ai​≤109)——每种口味一袋的成本。

输出

对于每个测试用例,打印一个整数——购买一袋任何口味的零钱所需的最少硬币数。

code:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

typedef pair<int,int> pii;

const int maxn=1e6+5;

int a[maxn], b[maxn];

int cnt[3];

void solve(){

int n;

cin >> n;

cnt[0] = cnt[1] = cnt[2] = 0;

int res = 0, max_a = 0, flag_1 = 0, flag_max = 0;;

for(int i = 1; i <= n; i ++) {

cin >> a[i];

cnt[a[i] % 3] ++;

res = max(res, a[i] / 3);

max_a = max(max_a, a[i]);

if(a[i] == 1) flag_1 = 1;

}

for(int i = 1; i <= n; i ++) {

if(max_a - 1 == a[i]) {

flag_max = 1;

}

}

if(cnt[1] == cnt[2] && cnt[1] == 0) {

cout << res << '\n';

}

else if(cnt[2] == 0 || cnt[1] == 0) {

cout << res + 1 << '\n';

}

else if(max_a % 3 == 0) {

cout << res + 1 << '\n';

}

else if(max_a % 3 == 1 && !flag_1 && !flag_max) {

cout << res + 1 << '\n';

}

else {

cout << res + 2 << '\n';

}

}

int main(){

ios::sync_with_stdio(0);

int t;

cin >> t ;

while(t--){

solve();

}

return 0;

}

E. Replace the Numbers

=========================================================================================

题目描述


您有一个整数数组(最初为空)。

您必须执行 q 查询。 每个查询属于以下两种类型之一:

"1 x" — 将元素 x 添加到数组的末尾;

"2 x y" — 用 y 替换数组中所有出现的 x。

执行所有查询后找到结果数组。

输入

第一行包含一个整数 q ( 1 ≤ q ≤ 5 ⋅ 1 0 5 ) q (1≤q≤5⋅10^5) q(1≤q≤5⋅105)——查询的数量。

接下来的 q 行包含查询(每行一个)。 每个查询属于以下两种类型之一:

" 1 x " ( 1 ≤ x ≤ 5 ⋅ 1 0 5 ) "1 x" (1≤x≤5⋅10^5) "1x"(1≤x≤5⋅105);

" 2 x y " ( 1 ≤ x , y ≤ 5 ⋅ 1 0 5 ) "2 x y" (1≤x,y≤5⋅10^5) "2xy"(1≤x,y≤5⋅105)。

保证至少有一个第一种类型的查询。

输出

在一行中,打印 k 个整数——执行所有查询后的结果数组,其中 k 是第一种类型的查询数。

code:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef long double ld;

typedef pair<int, int> pii;

const int maxn = 1e6 + 5;

int q;

map<int, int> m;

vector<pair<int, int>> qs;

void solve()

{

cin >> q;

for (int i = 0; i < q; i++)

{

int t;

cin >> t;

qs.push_back({-1, -1});

if (t == 1)

cin >> qs.back().second;

else

cin >> qs.back().first >> qs.back().second;

}

vector ans;

for (int i = q - 1; i >= 0; i--)

{

if (m[qs[i].second] == 0)

m[qs[i].second] = qs[i].second;

if (qs[i].first == -1)

ans.push_back(m[qs[i].second]);

else

m[qs[i].first] = m[qs[i].second];

}

reverse(ans.begin(),ans.end());

for (auto x : ans)

cout << x << ' ';

cout << '\n';

}

int main()

{