标签:std AtCoder y2 Beginner int i64 258 y1 x1
咕咕咕咕。
E - Packing Potatoes
题意
有无穷多个土豆,第\(i\)个土豆的质量为\(w_i\),给定\(w\)的前\(n\)项,然后\(w_{i + n} = w_i\)。
有一个打包流程,一个袋子有个参数\(x\),不断将土豆放进这个袋子知道袋子中土豆质量和大于等于\(x\),然后封袋并使用一个新袋子继续打包。
要求回答\(q\)个询问,第\(i\)个询问需要回答第\(k_i\)个袋子里装了多少个土豆。
其中\(1 \le n, q \le 2 \times {10}^5, 1 \le x, w_i \le {10}^9, 1 \le k_i \le {10}^{12}\)。
思路
倍增。
首先,从第\(0 \le i < n\)个土豆开始打包,所用的袋子中土豆数量以及新袋子从哪一个土豆开始,这个可以二分求。
然后,这个相当于走\(1\)步结果,通过binary lifting可以处理出走\(2^j\)步的结果。
最后再将\(k\)拆分成二进制然后走就可以了。
AC代码
// Problem: E - Packing Potatoes
// Contest: AtCoder - AtCoder Beginner Contest 258
// URL: https://atcoder.jp/contests/abc258/tasks/abc258_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)
#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif
using i64 = int64_t;
using u64 = uint64_t;
void solve_case(int Case);
int main(int argc, char* argv[]) {
CPPIO;
int T = 1;
// std::cin >> T;
for (int t = 1; t <= T; ++t) {
solve_case(t);
}
return 0;
}
void solve_case(int Case) {
int n, q;
i64 x;
std::cin >> n >> q >> x;
std::vector<i64> w(n), s(n + 1);
for (int i = 0; i < n; ++i) {
std::cin >> w[i];
s[i + 1] = s[i] + w[i];
}
auto get = [&](i64 p) { return (p / n) * s[n] + s[p % n]; };
std::vector<int> c(n);
i64 lg = 40;
std::vector<std::vector<int>> f(lg + 1, std::vector<int>(n));
for (int i = 0; i < n; ++i) {
i64 l = i + 1, r = i + x, mid, nxt = i + 1;
while (l <= r) {
mid = (l + r) >> 1;
if (get(mid) - s[i] >= x)
r = mid - 1, nxt = mid;
else
l = mid + 1;
}
f[0][i] = nxt % n;
c[i] = nxt - i;
}
logd(c);
for (int i = 1; i <= lg; ++i) {
for (int j = 0; j < n; ++j) {
f[i][j] = f[i - 1][f[i - 1][j]];
}
}
for (int i = 0; i < q; ++i) {
i64 k;
std::cin >> k;
--k;
int p = 0;
for (int j = 40; j >= 0; --j) {
if ((k >> j) & 1) {
p = f[j][p];
}
}
std::cout << c[p] << "\n";
}
}
F - Main Street
题意
二维平面上有多条路,对于任意整数\(n\),\(x = n\)是一条路,\(y = n\)是一条路。
然后,在这些路中\(x = bn\)和\(y = bn\)是主路。
支持往上下左右4个方向移动一步,在主路上耗时为1秒,在其他路上耗时为\(k\)秒。
问从点\((sx, sy)\)移动到点\((tx, ty)\)的最小耗时。
其中\(1 \le b, k \le {10}^9, 0 \le sx, sy, tx, ty \le {10}^9\)。
思路
答案最差不会超过两点manhattan距离的\(k\)倍。
然后可能可以借助主路来降低耗时,这个需要先走到主路上。
易得只需要考虑直线走到主路上的路线,所以起点和终点可以对应到4个主路上的点,分别记为\(S\)和\(T\)。
为了方便计算,可以将路径拆分成3段:从起点走到\(S\)中的点,在主路上从\(S\)中的点走到\(T\)中的点,最后从\(T\)中的点走到终点。
然后分别枚举\(S\)和\(T\)中的点,计算代价取最小值即可。
AC代码
// Problem: F - Main Street
// Contest: AtCoder - AtCoder Beginner Contest 258
// URL: https://atcoder.jp/contests/abc258/tasks/abc258_f
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)
#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif
using i64 = int64_t;
using u64 = uint64_t;
void solve_case(int Case);
int main(int argc, char* argv[]) {
CPPIO;
int T = 1;
std::cin >> T;
for (int t = 1; t <= T; ++t) {
solve_case(t);
}
return 0;
}
void solve_case(int Case) {
auto manhattan = [](const std::array<i64, 2>& p1, const std::array<i64, 2>& p2) -> i64 {
return std::abs(p2[0] - p1[0]) + std::abs(p2[1] - p1[1]);
};
i64 B, K;
i64 sx, sy, tx, ty;
std::cin >> B >> K;
std::cin >> sx >> sy >> tx >> ty;
auto get1 = [&B, &K, &manhattan](i64 x, i64 y) -> std::vector<std::array<i64, 3>> {
std::vector<i64> X = {x / B * B, (x / B * B) + B};
std::vector<i64> Y = {y / B * B, (y / B * B) + B};
std::vector<std::array<i64, 3>> result;
for (i64 nx : X) {
result.push_back({nx, y, K * manhattan({x, y}, {nx, y})});
}
for (i64 ny : Y) {
result.push_back({x, ny, K * manhattan({x, y}, {x, ny})});
}
return result;
};
auto get2 = [&B, &K, &manhattan](i64 x1, i64 y1, i64 x2, i64 y2) -> i64 {
i64 cost;
if (x1 % B == 0 && x2 % B == 0 && y1 / B == y2 / B) {
cost = std::min(K * std::abs(x2 - x1) + std::abs(y2 - y1),
std::abs(x2 - x1) + std::min(y1 % B + y2 % B, 2 * B - y1 % B - y2 % B));
} else if (y1 % B == 0 && y2 % B == 0 && x1 / B == x2 / B) {
cost = std::min(std::abs(x2 - x1) + K * std::abs(y2 - y1),
std::abs(y2 - y1) + std::min(x1 % B + x2 % B, 2 * B - x1 % B - x2 % B));
} else {
cost = manhattan({x1, y1}, {x2, y2});
}
return cost;
};
i64 ans = K * manhattan({sx, sy}, {tx, ty});
auto S = get1(sx, sy);
auto T = get1(tx, ty);
for (const auto& [x1, y1, c1] : S) {
for (const auto& [x2, y2, c2] : T) {
ans = std::min(ans, c1 + c2 + get2(x1, y1, x2, y2));
}
}
std::cout << ans << "\n";
}
G - Triangle
靠std::bitset
加速能暴力水过去。
Ex - Odd Steps
TBA。
标签:std,AtCoder,y2,Beginner,int,i64,258,y1,x1 来源: https://www.cnblogs.com/zengzk/p/16441494.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。