2009(971div4)
A. Minimize!
cout << b - a << '\n';
B. osu! mania
钢琴块落下
void solve() {
int n;cin >> n;
vector<int> ans;
for (int i = 0;i < n;i++) {
string s;cin >> s;
for (int j = 0;j < s.size();j++) {
if (s[j] == '#') {
ans.push_back(j + 1);
}
}
}
reverse(ans.begin(), ans.end());
for (auto x : ans)cout << x << ' ';cout << '\n';
}
C. The Legend of Freya the Frog
青蛙弗莱娅正在二维坐标平面上旅行。她目前在点
最初,她面向的是
她最少要走多少步才能到达点
初步很容易想到答案是
,但不容易想到要减去 1 的情况,当 需要比 多走一步时,最后一步只需要将 方向走完即可,不需要再走 方向。
void solve() {
int x, y, k;cin >> x >> y >> k;
if ((x + k - 1) / k <= (y + k - 1) / k) {
cout << (max(x, y) + k - 1) / k * 2 << '\n';
} else {
cout << (max(x, y) + k - 1) / k * 2 - 1 << '\n';
}
}
D. Satyam and Counting
给出了
如果有一个点
只有两种情况能组成直角三角形:
- 当两个点横坐标相同时
- 当横坐标为
且满足构成直角三角形时
#define int long long
void solve() {
int n;cin >> n;
vector<int> vis(n + 1);
map<pair<int, int>, int>mp;
int cnt = 0;
for (int i = 1;i <= n;i++) {
int x, y;cin >> x >> y;mp[{x, y}] = 1;
vis[x]++;
if (vis[x] == 2) {
cnt++;
}
}
int ans = cnt * (n - 2);
for (int i = 0;i <= n - 2;i++) {
if (mp.count({i,0}) && mp.count({i + 1,1}) && mp.count({i + 2,0}))ans++;
if (mp.count({i,1}) && mp.count({i + 1,0}) && mp.count({i + 2,1}))ans++;
}
cout << ans << '\n';
}
E. Klee's SUPER DUPER LARGE Array!!!
Klee 有一个长度为
输出
二分出正负数的边界即可
Q: 可不可以不使用二分而通过数学的方式
#define int long long
void solve() {
int n, k;cin >> n >> k;
auto cal = [&](int i) {
return 2 * i * k + i * (i - 1) - n * k - n * (n - 1) / 2;
};
int l = 1, r = n + 1;
while (l < r) {
int i = l + r >> 1;
int ans = cal(i);
if (ans >= 0) {
r = i;
} else {
l = i + 1;
}
}
cout << min(cal(l), -cal(l - 1)) << '\n';
}
F. Firefly's Queries
给定长度为
然后,她会向你提出
将区间分为三个部分:
,拆开做将两边多余的部分删除即可 (大模拟做法)
Solution
#define int long long
void solve() {
int n, q;cin >> n >> q;
vector<int> a(n + 1), pre(n + 1);
for (int i = 1;i <= n;i++)cin >> a[i];
for (int i = 1;i <= n;i++) {
pre[i] = pre[i - 1] + a[i];
}
int sum = accumulate(a.begin() + 1, a.end(), 0ll);
while (q--) {
int l, r;cin >> l >> r;
int ans = sum * n;
int x = (l - 1) / n;
int yu = (l - 1) % n;
ans -= sum * x;
if (yu <= n - x) {
ans -= pre[x + yu] - pre[x];
} else {
ans -= pre[n] - pre[x];
yu -= n - x;
ans -= pre[yu];
}
x = (n * n - r) / n;
yu = (n * n - r) % n;
ans -= sum * x;
if (yu <= n - x - 1) {
ans -= pre[n - x - 1] - pre[n - x - 1 - yu];
} else {
ans -= pre[n - x - 1];
yu -= n - x - 1;
ans -= pre[n] - pre[n - yu];
}
cout << ans << '\n';
}
}
法二:(官方题解)
复制数组
可以证明,对于任意整数
void solve() {
ll n, q;
cin >> n >> q;
vector<ll> a(n), ps(1);
for (ll &r : a) {
cin >> r;
ps.push_back(ps.back() + r);
}
for (ll &r : a) {
ps.push_back(ps.back() + r);
}
while (q--) {
ll l, r;
cin >> l >> r;
l--; r--;
ll i = l / n, j = r / n;
l %= n; r %= n;
cout << ps[n] * (j - i + 1) - (ps[i + l] - ps[i]) - (ps[j + n] - ps[j + r + 1]) << "\n";
}
}
G1. Yunli's Subarray Queries (easy version)
这是问题的简单版本。在这个版本中,保证所有查询都是
对于任意数组
- 选择索引
。设置 ,其中 是她想要的任意整数( 不限于区间 )。
将
给云莉一个大小为
Solution
滑动窗口
所有区间长度都是
对于一个区间,连续子数组
的要求,否则只需要查看区间内出现次数最多的元素即可,需要操作的次数则为
每次是从区间
void solve() {
int n, k, q;cin >> n >> k >> q;
vector<int> a(n + 1);
multiset<int>s;
map<int, int>mp;
for (int i = 1;i <= n;i++)cin >> a[i], s.insert(0);
auto op = [&](int i, int x) {
s.erase(s.find(mp[a[i] - i]));
mp[a[i] - i] += x;
s.insert(mp[a[i] - i]);
};
for (int i = 1;i < k;i++) {
op(i, 1);
}
vector<int> ans(n + 1);
for (int i = k;i <= n;i++) {
op(i, 1);
ans[i] = k - *s.rbegin();
op(i - k + 1, -1);
}
while (q--) {
int l, r;cin >> l >> r;
cout << ans[r] << '\n';
}
}
G2,G3
暂且不补