ABC339 A-G

2024-02-04 02:12
文章标签 abc339

本文主要是介绍ABC339 A-G,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contest 339) - AtCoder

离AK ABC最近的一集,写完F还剩十分钟聊天去了,赛后一看题一眼主席树贴板子改一改十分钟过了...前几题感觉真的阅读理解...

A - TLD

题意:

给出一个由小写英文字符和'.'构成的字符串,输出该字符串中最后一个'.'之后的部分

代码:

char ch[N];
void solve()
{scanf("%s", ch + 1);int p = 1;for (int i = 1; ch[i]; ++i){if (ch[i] == '.')p = i + 1;}printf("%s", ch + p);
}

B - Langton's Takahashi

题意:

有一张H*W的矩阵,刚开始矩阵的每个格子都是白色的,这个矩阵上下左右是成环的(也就是说每一行的第w个格子右边是这行的第一个格子,列上同理)

你刚开始位于(1, 1)且面朝上,你将进行以下操作N次:

1、若当前格子是白色的,将这个格子染成黑色,右转(顺时针)90°,向前走一格

2、若当前格子是黑色的,将这个格子染成白色,左转(逆时针)90°,向前走一格

输出经过所有操作后的矩阵

题解:

若至阅读理解题,模拟即可

int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 }, mp[N][N];
void solve()
{int h, w, n, x = 1, y = 1, op = 0;scanf("%d%d%d", &h, &w, &n);while (n--){if (!mp[x][y])mp[x][y] = 1, op = (op + 1) % 4;elsemp[x][y] = 0, op = (op + 3) % 4;x += dx[op], y += dy[op];x = (x - 1 + h) % h + 1, y = (y - 1 + w) % w + 1;}for (int i = 1; i <= h; ++i){for (int j = 1; j <= w; ++j){if (mp[i][j])printf("#");else printf(".");}printf("\n");}
}

C - Perfect Bus

题意:

有辆公交车,你不知道初始时它装了多少乘客人,接下来这两公交车经过了N站,每一站乘客的人数变化为Ai(为正则为上车人数,为负则为下车人数),问经过这N站之后车上乘客数量的最小值

题解:

设初始人数为0,模拟一下,设模拟过程中的最小值为mn,则-mn为最小的初始乘客数

void solve()
{LL n, s = 0, mn = 0, mx = 0;scanf("%lld", &n);for (int i = 1, x; i <= n; ++i){scanf("%d", &x);s += x;mn = min(mn, s);}printf("%lld\n", -mn + s);
}

D - Synchronized Players

题意:

给出一张N*N的地图,'.'为能走的道路,'#'为不能走的墙壁,'P'为两个玩家,你可以对两名玩家进行以下操作任意次:让两名玩家同时尝试向上/下/左/右移动一格,若能移动则移动,不能在站在原地。问最少多少步使两名玩家位置重合,不能输出-1

题解:

考虑到N很小,设dp[x1][y1][x2][y2]为使得玩家1在(x1, y1)位置,玩家2在(x2, y2)位置的最小操作数,bfs转移一下即可,数据极限情况挺极限的,用map存T了一发...

const LL N = 6e1 + 10;
char mp[N][N];
int dp[N][N][N][N];
queue<pair<PII, PII>>q;
int dx[] = { 0,0,1,-1 }, dy[] = { 1,-1,0,0 };
PII op(PII p, int t)
{int tx = p.first + dx[t], ty = p.second + dy[t];if (mp[tx][ty] != '#')return { tx,ty };return p;
}
void solve()
{int n;scanf("%d", &n);vector<PII>s;for (int i = 0; i <= n + 1; ++i){for (int j = 0; j <= n + 1; ++j)mp[i][j] = '#';}for (int i = 1; i <= n; ++i){getchar();for (int j = 1; j <= n; ++j){mp[i][j] = getchar();if (mp[i][j] == 'P')s.push_back({ i,j });}}q.push({ s[0],s[1] });dp[s[0].first][s[0].second][s[1].first][s[1].second] = 1;while (q.size()){PII a = q.front().first, b = q.front().second;if (a == b){printf("%d\n", dp[a.first][a.second][b.first][b.second] - 1);return;}q.pop();for (int i = 0; i < 4; ++i){PII ta = op(a, i), tb = op(b, i);if (!dp[ta.first][ta.second][tb.first][tb.second]){dp[ta.first][ta.second][tb.first][tb.second] = dp[a.first][a.second][b.first][b.second ]+ 1;q.push({ ta,tb });}}}printf("-1\n");
}

E - Smooth Subsequence

题意:

给出一个长度为N的数组A,求一个最长的子序列使得相邻元素之间差值的绝对值不大于D

题解:

线段树优化DP,设dp[x]为以值x结尾时最长的子序列长度,转移为dp[x]=max({dp[i], x - d <= i <= x + d}) + 1,处理一下两边界然后线段树优化即可

const LL N = 5e5 + 10;
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
int a[N], tr[N << 2];
void updata(int pos, int data, int l, int r, int i)
{if (l == r){tr[i] = data;return;}int mid = l + r >> 1;if (pos <= mid)updata(pos, data, l, mid, ls(i));else updata(pos, data, mid + 1, r, rs(i));tr[i] = max(tr[ls(i)], tr[rs(i)]);
}
int query(int ql, int qr, int l, int r, int i)
{if (ql <= l && r <= qr)return tr[i];int mid = l + r >> 1, res = 0;if (mid >= ql)res = max(res, query(ql, qr, l, mid, ls(i)));if (mid < qr)res = max(res, query(ql, qr, mid + 1, r, rs(i)));return res;
}
void solve()
{int n, d;scanf("%d%d", &n, &d);for (int i = 1, x; i <= n; ++i){scanf("%d", &x);int l = max(1, x - d), r = min((int)N, x + d);updata(x, query(l, r, 1, N, 1) + 1, 1, N, 1);}printf("%d\n", query(1, N, 1, N, 1));
}

F - Product Equality

题意:

给出一个长度为N的大数数组,求符合以下条件的三元组(i , j, k)数量:

1 <= i, j, k <= n,Ai * Aj = Ak

题解:

随机化哈希,刚好前段时间做过一道随机化哈希的题...

显然用高精度是做不了的,然后这题要求啊Ai * Aj = Ak显然在取模意义下也是成立的,那就可以对每个数都取模,这样问题就变成了1e3个普通32(或64)位整数之间的问题,枚举i, j然后查询符合条件的Ak数量(比如说存进map)即可,取模数建议生成随机数取,还可以多模,这样多能降低被卡的概率

const LL N = 1e3 + 10;
string s[N];
array<int, 6>a[N];
map<array<int, 6>, int>mp;
int mod[10] = { 998244353,51646229,68861641,91815541,91815541,(int)1e9 + 7 };
//atc没有hack这里就随便取几个数了(随机生成高质量随机数还不会用...)
//有点抽象的六模的哈希
array<int, 6> make_ar(string& t)
{array<int, 6>res = { 0,0,0,0,0,0 };for (auto& c : t){int f = c - '0';for (int i = 0; i < 6; ++i)res[i] = ((LL)res[i] * 10 + f) % mod[i];}return res;
}
array<int, 6> operator*(array<int, 6>x, array<int, 6>y)
{array<int, 6>res;for (int i = 0; i < 6; ++i)res[i] = (LL)x[i] * y[i] % mod[i];return res;
}
void solve()
{int n;scanf("%d", &n);for (int i = 1; i <= n; ++i){cin >> s[i];a[i] = make_ar(s[i]);++mp[a[i]];}int ans = 0;for (int i = 1; i <= n; ++i){for (int j = 1; j <= n; ++j){array<int, 6>res = a[i] * a[j];if (mp.find(res) != mp.end())ans += mp[res];}}printf("%d\n", ans);
}

G - Smaller Sum

题意:

给出一个长度为N的数组A,有Q个询问,每个询问要求求出从子串Li, Ri中所有不小于Xi的元素之和(强制在线)

题解:

一眼看着像主席树,然后对主席树改一改,维护的东西多加个维护sum就行了

const LL N = 2e5 + 10, M = 1e9 + 10;
#define ls(x) (tr[x].ls)
#define rs(x) (tr[x].rs)
#define s(x) tr[x].s
#define sum(x) tr[x].sum
struct node
{int ls, rs, s;LL sum;
}tr[32 * N];//logM * N
int root[N], tot;
void push_up(int i)
{s(i) = s(ls(i)) + s(rs(i));sum(i) = sum(ls(i)) + sum(rs(i));
}
void updata(int pos, int data, int l, int r, int last, int now)
{if (l == r){s(now) = s(last) + data;sum(now) = sum(last) + (LL)data * pos;return;}ls(now) = ls(last), rs(now) = rs(last);int mid = l + r - 1 >> 1;if (pos <= mid)updata(pos, data, l, mid, ls(last), ls(now) = ++tot);elseupdata(pos, data, mid + 1, r, rs(last), rs(now) = ++tot);push_up(now);
}
void updata(int pos, int data, int last, int now)
{updata(pos, data, -M, M, last, now);
}
LL query_range_sum(int ql, int qr, int l, int r, int last, int now)
{if (ql <= l && r <= qr)return sum(now) - sum(last);LL mid = l + r - 1 >> 1, res = 0;if (ql <= mid)res += query_range_sum(ql, qr, l, mid, ls(last), ls(now));if (qr > mid)res += query_range_sum(ql, qr, mid + 1, r, rs(last), rs(now));return res;
}
LL query_range_sum(int ql, int qr, int last, int now)
{return query_range_sum(ql, qr, -M, M, last, now);
}
void solve()
{int n;scanf("%d", &n);for (int i = 1, x; i <= n; ++i){scanf("%d", &x);root[i] = ++tot;updata(x, 1, root[i - 1], root[i]);}int q;scanf("%d", &q);LL ans = 0;while (q--){LL l, r, x;scanf("%lld%lld%lld", &l, &r, &x);l ^= ans, r ^= ans, x ^= ans;ans = query_range_sum(1, x, root[l - 1], root[r]);printf("%lld\n", ans);}
}

看完题意感觉像是主席树,然后一想不对好像可以离线,再一看离线被ban了,再想想主席树做法发现完全能做...板子改改一发过了

这篇关于ABC339 A-G的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/676101

相关文章

Atcoder ABC339 D - Synchronized Players

Synchronized Players(同步的球员) 时间限制:4s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输入1】 5....##..#..P.....P......# 【样例输出1】 3

Atcoder ABC339 B - Langton‘s Takahashi

Langton’s Takahashi(兰顿的高桥) 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输入1】 3 4 5 【样例输出1】 .#..##...... 【样例说明1】 【

Atcoder ABC339 C - Perfect Bus

Perfect Bus(完美的公交车) 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输入1】 43 -5 7 -4 【样例输出1】 3 【样例说明1】 【样例2】 【样例输入2】

Atcoder ABC339 A - TLD

TLD 时间限制:2s 内存限制:1024MB 【原题地址】 所有图片源自Atcoder,题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输入1】 atcoder.jp 【样例输出1】 jp 【样例说明1】 【样例2】 【样例输入2】 translate.googl

Atcoder ABC339 A-D题解

除夕晚上的比赛,傻子才打。 Problem A: 简单题。但是相比于之前的A题来说还是变难了。直接上代码: #include <bits/stdc++.h>using namespace std;int main(){string str;cin>>str;int pos=-1;for(int i=1;i<str.size();i++){if(str[i]=='.')pos=i;}cou