题意 从左到右选择四列,使得四列分别对应字母 v , i , k , a v,i,k,a v,i,k,a
string solve() {
int n, m; cin >> n >> m;
char s[N][N];
char a[5] = "vika";
int cnt = 0;
for (int i = 0; i < n; i ++) cin >> s[i];
for (int j = 0; j < m; j ++)
for (int i = 0; i < n; i ++)
if (s[i][j] == a[cnt]) {
cnt ++;
break;
}
if (cnt == 4) return yes;
return no;
}
题意 从 a a a 序列经过转换变成 b b b 序列,已知 b b b 序列,求任意一个可能的 a a a 序列
首先 b 0 ← a 0 b_0 ← a_0 b0←a0,然后只要满足 a i − 1 ≤ a i a_{i-1}\le a_i ai−1≤ai 就将 a i p u s h _ b a c k a_i~push\_back ai push_back 到 b b b 序列后面
void solve() {
int n; cin >> n;
vector<int> a(1);
cin >> a[0];
for (int i = 1; i < n; i ++) {
int x; cin >> x;
if (*(a.end() - 1) > x) a.push_back(x);
a.push_back(x);
}
cout << a.size() << endl;
for (auto i : a) cout << i << ' ';
cout << endl;
}
题意 给出每个栅栏的高度(宽度为 1 1 1),问这个栅栏是否关于 y = x y=x y=x 对称
string solve() {
int n; cin >> n;
vector<int> a(n);
for (auto &i : a) cin >> i;
a.push_back(0);
int idx = 0;
for (int i = n - 1; i >= 0; i --) {
int t = a[i] - a[i + 1];
while (t --) if (a[idx ++] != i + 1) return no;
}
return yes;
}
题意 每两种球可以合成一种冰淇淋,且 ( i , j ) = ( j , i ) (i,j)=(j,i) (i,j)=(j,i)。特殊的,两个球 1 1 1 可以合成 ( 1 , 1 ) (1,1) (1,1)。问至少需要多少球能刚好合成 n n n 个冰淇淋
ll solve() {
ll n; cin >> n;
ll l = 0, r = 2e9;
while (l < r) {
ll mid = l + r + 1 >> 1;
if (mid * (mid - 1) / 2 <= n) l = mid;
else r = mid - 1;
}
ll res = l + (n - l * (l - 1) / 2);
return res;
}
题意 一共 n n n 天每天一场电影,最多看 m m m 场电影,每场电影的热度为 a i a_i ai,每次看电影的兴奋值为 a i − c n t ⋅ d a_i-cnt·d ai−cnt⋅d,其中 d d d 为给定常数, c n t cnt cnt 为距上次看电影的天数,求最终的兴奋值之和
题解 优先队列
ll solve() {
int n, m, d; cin >> n >> m >> d;
priority_queue<int, vector<int>, greater<int>> q;
ll res = 0, sum = 0;
for (int i = 1; i <= n; i ++) {
int x; cin >> x;
if (x <= 0) continue;
if (q.size() < m) {
sum += x;
q.push(x);
} else {
sum += x;
q.push(x);
sum -= q.top();
q.pop();
}
res = max(res, sum - (ll)i * d);
}
return res;
}
题意 有 n n n 个怪兽血量为 a i a_i ai,魔法师初始有 0 0 0 点水魔法和 0 0 0 点火魔法,每秒分别恢复 w , f w,f w,f 点,对于每个怪兽只能
法一: b i t s e t bitset bitset
int solve() {
int n, w, f; cin >> w >> f >> n;
bitset<N> b;
b[0] = true;
int sum = 0;
for (int i = 1; i <= n; i ++) {
int x; cin >> x;
sum += x;
b |= b << x;
}
int res = sum;
for (int i = 0; i <= sum; i ++) {
if (!b[i]) continue;
int x = (i + w - 1) / w;
int y = (sum - i + f - 1) / f;
res = min(res, max(x, y));
}
return res;
}
法二: d p dp dp 因为是从二维优化到一维,因此 j j j 逆序枚举
int solve() {
int n, w, f; cin >> w >> f >> n;
vector<int> a(n);
int sum = 0;
for (auto &i : a) cin >> i, sum += i;
vector<int> dp(sum + 1);
dp[0] = 1;
for (auto i : a)
for (int j = sum; j >= i; j --)
dp[j] |= dp[j - i];
int res = sum;
for (int i = 0; i <= sum; i ++) {
if (!dp[i]) continue;
int x = (i + w - 1) / w;
int y = (sum - i + f - 1) / f;
res = min(res, max(x, y));
}
return res;
}