abc331 a-爱代码爱编程
Daiwa Securities Co. Ltd. Programming Contest 2023(AtCoder Beginner Contest 331) - AtCoder
掉大分的一场。D好若至调了好久,EF倒是全都一眼出做法...然而F手搓写bug了直到赛后才找到sb错误...
A - Tomorrow
题意:
每年M月,每个月D天,求y年m月d日的下一天的日期
题解:
void solve()
{
int m, d, a, b, c;
scanf("%d%d%d%d%d", &m, &d, &a, &b, &c);
if (++c > d)
{
c = 1;
if (++b > m)
b = 1, ++a;
}
printf("%d %d %d\n", a, b, c);
}
B - Buy One Carton of Milk
题意:
超市里有盒装鸡蛋,六只装S元,八只装M元,十二只装L元,问购买不少于N个蛋要至少多少元
题解:
简单dp即可
int dp[N];
void solve()
{
memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
int n, s, m, l;
scanf("%d%d%d%d", &n, &s, &m, &l);
for (int i = 1; i <= n + 12; ++i)
{
if (i >= 6)dp[i] = dp[i - 6] + s;
if (i >= 8)dp[i] = min(dp[i], dp[i - 8] + m);
if (i >= 12)dp[i] = min(dp[i], dp[i - 12] + l);
}
int ans = INF;
for (int i = n; i <= n + 12; ++i)
ans = min(ans, dp[i]);
printf("%d\n", ans);
}
C - Sum of Numbers Greater Than Me
题意:
给出一个场为N的数组A,问对于每个i输出A中所有大于Ai值的元素之和
题解:
前缀(后缀)和,注意数据会爆int
const int N = 1e6 + 10;
LL a[N], s[N];
void solve()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &a[i]);
s[a[i]] += a[i];
}
for (int i = N - 2; i >= 0; --i)
s[i] += s[i + 1];
for (int i = 1; i <= n; ++i)
{
printf("%lld ", s[a[i] + 1]);
}
}
D - Tile Pattern
题意:
给出一个N*N的仅由'W'和'B'构成的字符矩阵,它会在平面内无限延展(如样例1的图),给出Q个询问,每个询问需要求出从(a, b)到(c, d)的矩形区域中黑色块('B')的数量
题解:
思路其实很简单,首先计算一片区域内'B'的数量能想到二维前缀和,其次我们可以把这个矩阵分割成几块然后分别求数量然后相加。
在有了以上基础做法之后我们再想如何简单的求出,先把分割出的区域看成9块,然后我们发现左上左下右上右下四块可以拼成一块来计算,左右拼一块,上下拼一块,正中间的一块,然后就这么做,注意细节即可(然后我这个若至就在这里花了40多分钟),这里把N*N的图扩展一下变成2N*2N的图能便于求解
int s[N][N];
int get_sum(int ux, int uy, int vx, int vy)
{
return s[vx][vy] - s[ux - 1][vy] - s[vx][uy - 1] + s[ux - 1][uy - 1];
}
void solve()
{
int n, q;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i)
{
getchar();
for (int j = 1; j <= n; ++j)
{
s[i][j] = (getchar() == 'B');
s[i + n][j] = s[i][j + n] = s[i + n][j + n] = s[i][j];
}
}
for (int i = 1; i <= 2 * n; ++i)
{
for (int j = 1; j <= 2 * n; ++j)
s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
}
while (q--)
{
int ux, uy, vx, vy;
scanf("%d%d%d%d", &ux, &uy, &vx, &vy);
++vx, ++vy;
int tux = ux % n, tvx = vx % n, tuy = uy % n, tvy = vy % n;
if (tvx < tux)tvx += n;
if (tvy < tuy)tvy += n;
//printf("%d %d %d %d\n", tux, tuy, tvx, tvy);
LL sx = (vx - ux) / n, sy = (vy - uy) / n;
//printf("%lld %lld\n", sx, sy);
LL ans = get_sum(tux + 1, tuy + 1, tvx, tvy);
ans += sx * get_sum(1, tuy + 1, n, tvy);
ans += sy * get_sum(tux + 1, 1, tvx, n);
ans += sx * sy * get_sum(1, 1, n, n);
printf("%lld\n", ans);
}
}
E - Set Meal
题意:
餐厅给出N主菜,M道配菜,每道主菜的价格是ai,配菜的价格是bi,L中不能搭配在一起的组合ci, di,我们可以选择任意一道主菜+一道配菜(除了前面说的不能组合的)组成套餐,套餐的价格是ai+bi,求套餐价格的最大值
题解:
贪心,先将配菜存成对{价格,编号}然后使它按价格升序,将每个主菜不能搭配的配菜编存入set[i],遍历所有主菜,再从高价到低价遍历配菜,当遇到能做到的搭配时直接计算价格与答案取max然后break即可
int a[N];
PII b[N];
set<int>st[N];
void solve()
{
int n, m, l;
scanf("%d%d%d", &n, &m, &l);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
st[i].clear();
}
for (int i = 1; i <= m; ++i)
{
scanf("%d", &b[i].first);
b[i].second = i;
}
sort(b + 1, b + 1 + m);
for (int i = 1; i <= l; ++i)
{
int c, d;
scanf("%d%d", &c, &d);
st[c].insert(d);
}
int ans = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = m; j >= 1; --j)
{
if (st[i].find(b[j].second) == st[i].end())
{
ans = max(ans, a[i] + b[j].first);
break;
}
}
}
printf("%d\n", ans);
}
F - Palindrome Query
题意:
给出一个长度为N的由小写字母构成的字符串以及Q次操作:
1:修改下标为x的字符为c;2:询问子串l, r是否为回文串
题解:
线段树维护字符串哈希,哈希自然溢出就能过
typedef long long LL;
typedef unsigned long long ULL;
const LL N = 1e6 + 10, P = 13331;
#define ls(i) (i<<1)
#define rs(i) (i<<1|1)
#define lh(i) tr[i].lh
#define rh(i) tr[i].rh
#define d(i) tr[i].d
struct node
{
int d;
ULL lh, rh;
}tr[N << 2];
ULL p[N];
void push_up(int i)
{
lh(i) = lh(ls(i)) * p[d(rs(i))] + lh(rs(i));
rh(i) = rh(ls(i)) + rh(rs(i)) * p[d(ls(i))];
}
void build(int l, int r, int i)
{
d(i) = r - l + 1;
if (l == r)
{
lh(i) = rh(i) = getchar();
return;
}
int mid = l + r - 1 >> 1;
build(l, mid, ls(i));
build(mid + 1, r, rs(i));
push_up(i);
}
void motify(int pos, int data, int l, int r, int i)
{
if (l == r)
{
lh(i) = rh(i) = data;
return;
}
int mid = l + r - 1 >> 1;
if (pos <= mid)motify(pos, data, l, mid, ls(i));
else motify(pos, data, mid + 1, r, rs(i));
push_up(i);
}
node query_range(int ql, int qr, int l, int r, int i)
{
if (ql <= l && r <= qr)
return tr[i];
int mid = l + r - 1 >> 1;
if (qr <= mid)return query_range(ql, qr, l, mid, ls(i));
if (ql > mid)return query_range(ql, qr, mid + 1, r, rs(i));
node ll = query_range(ql, qr, l, mid, ls(i)), rr = query_range(ql, qr, mid + 1, r, rs(i));
node res = { ll.d + rr.d, ll.lh * p[rr.d] + rr.lh, ll.rh + rr.rh * p[ll.d] };
return res;
}
void solve()
{
int n, q;
scanf("%d%d", &n, &q);
getchar();
p[0] = 1;
for (int i = 1; i <= n; ++i)
p[i] = p[i - 1] * P;
build(1, n, 1);
while (q--)
{
int op;
scanf("%d", &op);
if (op == 1)
{
int x;
char c;
scanf("%d %c", &x, &c);
motify(x, c, 1, n, 1);
}
else
{
int l, r;
scanf("%d%d", &l, &r);
node t = query_range(l, r, 1, n, 1);
if (t.lh == t.rh)
printf("Yes\n");
else
printf("No\n");
}
}
}
最搞笑的一集,看完题直接出做法然告诉队友之后开始手搓线段树,然后队友去贴板子小修一下直接过了,我写个bug调了20分钟爆金币了
感觉这个写的还蛮好的,以后可以直接当自己的板子用了