A. ?UPC
模拟
代码实现
print(input()[0]+'UPC')
B. Heavy Snake
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, d;
cin >> n >> d;
vector<int> t(n), l(n);
rep(i, n) cin >> t[i] >> l[i];
for (int k = 1; k <= d; ++k) {
int ans = 0;
rep(i, n) {
int w = t[i]*(l[i]+k);
ans = max(ans, w);
}
cout << ans << '\n';
}
return 0;
}
C. Various Kagamimochi
二分或双指针
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<int> A(n);
rep(i, n) cin >> A[i];
ll ans = 0;
rep(b, n) {
int r = upper_bound(A.begin(), A.begin()+b, A[b]/2) - A.begin();
ans += r;
}
cout << ans << '\n';
return 0;
}
D. Coming of Age Celebration
考虑实现以下功能的数据结构:
- 加入一个数
- 将集合中的所有数
-1 - 将集合中的
0删除 - 查询集合的大小
可以发现用小根堆就能做,时间复杂度为 \(O(n\log n)\)
也有一种 \(O(n)\) 做法
可以考虑每个外星人到哪一年就不需要再送石头了
具体可以维护变量 \(S\) 表示到目前为止已经有 \(S\) 个成年外星人需要送石头,再开一个 \(R\) 数组用来记录第 \(i\) 年之后不需要再送石头的成年外星人的人数
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
int s = 0;
vector<int> r(n);
rep(i, n) {
a[i] += s;
int num = min(a[i], n-i-1);
a[i] -= num;
s++;
r[i+num]++;
s -= r[i];
}
rep(i, n) cout << a[i] << ' ';
return 0;
}
E. Simultaneous Kagamimochi
二分出 \(k\)
对于判定是一种贪心,选择最左边 \(k\) 个放在蛋糕塔的上方,再将最右边的 \(k\) 个放在蛋糕塔的下方,然后每个上方的蛋糕选择下方还没被匹配的大小最小的进行配对
也可以双指针,左边一半放上方,右边一半放下方
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
int m = n/2, j = m;
int ans = 0;
rep(i, m) {
while (j < n and a[i]*2 > a[j]) j++;
if (j == n) break;
ans++;
j++;
}
cout << ans << '\n';
return 0;
}
F. Dangerous Sugoroku
当 \(B \leqslant R-L+1\) 时显然无解
先特殊处理一下 \(A=B\) 时的情况:可以发现每次走到的格子都是 \(1+Ak, k = 1, 2, \cdots\),如果可以走进 \([L, R]\) 中的格子,显然无解,另外如果 \(N-1\) 如果不是 \(A\) 的倍数也无解
对于一般情况可以矩阵快速幂优化dp,卡卡常就过了
再来考虑一下正经做法
我们可以先将这 \(N\) 个格子分成若干个只有好格子或只有坏格子的长条,不妨简单将前者记为好块,后者记为坏块
对于每个好块,我们只关心它后面 \(B\) 个格子能否到达
如果好块的长度大于 \(A^2\),且如果以上一个坏块为右端点,在它左边 \(B-1\) 个格子以内没有好格子到达的话,那么当前好块的最后 \(B\) 个好格子一定也就不会到达,也就更不可能到达第 \(N\) 个格子了;否则,最后 \(B\) 个好格子一定都会到达
对于其他情况,利用前 \(B-A+1\) 个格子的状态对好块正常转移即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
bool solve() {
ll n; int m, a, b;
cin >> n >> m >> a >> b;
vector<ll> l(m), r(m);
rep(i, m) cin >> l[i] >> r[i];
rep(i, m) l[i]--;
if (a == b) {
rep(i, m) {
ll x = (r[i]-1)/a*a;
if (l[i] <= x) return false;
}
if ((n-1)%a) return false;
return true;
}
vector<int> dp(b);
dp[0] = 1;
ll i = 0;
l.push_back(n); r.push_back(n); m++;
rep(j, m) {
ll w = l[j]-i-1;
if (w > a*a) {
if (dp == vector<int>(b, 0)) return false;
dp = vector<int>(b, 1);
}
else {
rep(k, w) {
dp.insert(dp.begin(), 0);
for (int x = a; x <= b; ++x) dp[0] |= dp[x];
dp.pop_back();
}
}
w = r[j]-l[j];
if (w >= b) return false;
rep(k, w) {
dp.insert(dp.begin(), 0);
dp.pop_back();
}
i = r[j]-1;
}
return dp[0] == 1;
}
int main() {
if (solve()) puts("Yes");
else puts("No");
return 0;
}
G. Simultaneous Kagamimochi 2
还是二分 \(k\)
令 \(w = r-l+1-k\)
对于 \(0 \leqslant i < k\),都应成立 \(2A_{l+i} \leqslant A_{l+w+i}\)
再令 \(X_i\) 表示使得 \(2A_i \leqslant A_j\) 成立的最小的 \(j\)
那么就有 \(X_{l+i} \leqslant l+w+i\),变形得到 \(X_{l+i} - (l+i) \leqslant w\)
记 \(Y_i = X_i - i\)
我们只需判定是否成立 \(\max(Y_l, \cdots, Y_{l+k-1}) \leqslant w\) 即可
对于左边的式子可以用st表或线段树来加速
代码实现
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace atcoder;
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int op(int a, int b) { return max(a, b); }
int e() { return 0; }
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<int> y(n);
{
int j = 0;
rep(i, n) {
while (j < n and a[i]*2 > a[j]) j++;
y[i] = j-i;
}
}
segtree<int, op, e> rmq(y);
int q;
cin >> q;
rep(qi, q) {
int l, r;
cin >> l >> r;
--l;
int ac = 0, wa = (r-l)/2+1;
while (abs(ac-wa) > 1) {
int wj = (ac+wa)/2;
bool ok = rmq.prod(l, l+wj) <= r-l-wj;
if (ok) ac = wj; else wa = wj;
}
cout << ac << '\n';
}
return 0;
}
浙公网安备 33010602011771号