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(nlogn)

也有一种 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

BRL+1 时显然无解
先特殊处理一下 A=B 时的情况:可以发现每次走到的格子都是 1+Ak,k=1,2,,如果可以走进 [L,R] 中的格子,显然无解,另外如果 N1 如果不是 A 的倍数也无解
对于一般情况可以矩阵快速幂优化dp,卡卡常就过了

再来考虑一下正经做法

我们可以先将这 N 个格子分成若干个只有好格子或只有坏格子的长条,不妨简单将前者记为好块,后者记为坏块
对于每个好块,我们只关心它后面 B 个格子能否到达
如果好块的长度大于 A2,且如果以上一个坏块为右端点,在它左边 B1 个格子以内没有好格子到达的话,那么当前好块的最后 B 个好格子一定也就不会到达,也就更不可能到达第 N 个格子了;否则,最后 B 个好格子一定都会到达
对于其他情况,利用前 BA+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=rl+1k
对于 0i<k,都应成立 2Al+iAl+w+i
再令 Xi 表示使得 2AiAj 成立的最小的 j
那么就有 Xl+il+w+i,变形得到 Xl+i(l+i)w
Yi=Xii
我们只需判定是否成立 max(Yl,,Yl+k1)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;
}