CF486题解
名称:安和昴
原材料:貌美40% 好胜40% 游戏20%
原产地:兵库县神户市
说明:善于为他人着想且沟通能力强。
可以安心地融入到即使是初见面的人很多的地方。
如果陪她玩游戏的话她会很开心。
但是由于本性好胜,她不赢就不会罢休,请悉知。
注意:请放在室内保管相当的宅家派
"昴です、よろしく"
486可爱捏
CF486A
\(\sum_{i=1}^nn(-1)^n=\sum_{i=1}^{\lfloor n/2\rfloor}[-(2i-1)+(2i)]-(n\bmod2)n=\lfloor n/2\rfloor-(n\bmod2)n\)
code:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int maxn = 5e5 + 10;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
cout << n / 2 + (n & 1 ? -n : 0);
return 0;
}
CF486B
如果 \(b_{i,j}=0\),那么第 \(i\) 行第 \(j\) 列都是 0,直接枚举模拟即可,然后判断 \(b_{i, j}=1\) 的位置的行列是否有 1 就好了
code:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int maxn = 5e5 + 10;
int a[105][105], b[105][105];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> b[i][j];
if (!b[i][j]) {
for (int k = 1; k <= m; k++) a[i][k] = 0;
for (int k = 1; k <= n; k++) a[k][j] = 0;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (b[i][j]) {
int ans = 0;
for (int k = 1; k <= m; k++) ans += a[i][k];
for (int k = 1; k <= n; k++) ans += a[k][j];
if (!ans) {
cout << "NO";
return 0;
}
}
}
}
cout << "YES" << endl;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
CF486C
先找到左右不同的位数,统计左半边的最小 \(mini\) 最大 \(maxi\)、右半边的最小 \(minj\) 最大 \(maxj\),然后讨论:
- 不存在不同的位数,输出 0
- \(n\bmod2=1,k = \lceil n/2\rceil\),这时走两边都一样,答案多加一个 \(k-mini\),要么 \(maxj-k\)
- \(k\le n/2\),这时只需要在一边走就行,那么再判断,
如果\(mini\le k, k \le maxi\),那么就需要走完其中一个再走另一个,所以最少是 \(2\min(maxi-k,k-mini)+\max(maxi-k,k-mini)\);
如果不是,那么要么在\(mini\)左边要么在\(maxi\)右边,答案加上一个\(\max(maxi-k,k-mini)\)就行 - \(k\ge n/2\),同理可得
code:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int maxn = 5e5 + 10;
int a[105][105], b[105][105];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, k, ans = 0, mini = 114514, minj = 114514, maxi = 0, maxj = 0;;
string s;
cin >> n >> k >> s;
k--;
for (int i = 0; i < n / 2; i++) {
int j = n - i - 1;
if (s[i] != s[j]) {
ans += min((s[i] - s[j] + 26) % 26, (s[j] - s[i] + 26) % 26);
mini = min(mini, i), minj = min(minj, j);
maxi = max(maxi, i), maxj = max(maxj, j);
}
}
if (mini != 114514) {
if (k == n / 2 && n & 1) ans += k - mini;
else if (k <= n / 2 - 1) {
if (mini <= k && k <= maxi) ans += 2 * min(maxi - k, k - mini) + max(maxi - k, k - mini);
else ans += max(k - mini, maxi - k);
}
else {
if (minj <= k && k <= maxj) ans += 2 * min(maxj - k, k - minj) + max(maxj - k, k - minj);
else ans += max(k - minj, maxj - k);
}
}
cout << ans;
return 0;
}
CF486D
令 \(f_u\) 为 \(u\) 子树下以 \(a_u\) 为最大点权的合法子图数,于是对于每个点,要么不选子树中的子图,要么选,即\(f_u=\prod(f_v+1)\),树形dp可做
code:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int maxn = 5e5 + 10, mod = 1e9 + 7;
int dp[2025], a[2025], d;
vector<int> g[2025];
void dfs(int u, int fa, int rt) {
dp[u] = 1;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (v == fa) continue;
if ((a[v] < a[rt] || (a[v] == a[rt] && v <= rt)) && a[rt] - a[v] <= d) {
dfs(v, u, rt);
(dp[u] += dp[u] * dp[v]) %= mod;
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, ans = 0;
cin >> d >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= n; i++) {
dfs(i, 0, i);
(ans += dp[i]) %= mod;
}
cout << ans;
return 0;
}
CF486E
令 \(s_i\) 为以 \(a_i\) 为结尾的LIS长度,\(p_i\) 为以 \(a_i\) 开头的LIS长度,显然,若总LIS长度为 \(len\) 且 \(a_i\) 是某一段总LIS中的,则 \(s_i+p_i-1=len\),这样可以判断第 \(i\) 位是不是1
再判断一下 \(s_i\) (\(p_i\)一样,反正都能互推) 的出现次数,如果多于1,则第 \(i\) 位为2,否则为3,因为出现多次的话在不同总LIS中可选可不选
求LIS用树状数组即可
code:
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int maxn = 1e5 + 10, mod = 1e9 + 7;
struct ta {
int t[maxn];
void clear() { memset(t, 0, sizeof t); }
int lowbit(int x) { return x & (-x); }
void add(int x, int k) {
while (x <= maxn) {
t[x] = max(t[x], k);
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while (x) {
ans = max(ans, t[x]);
x -= lowbit(x);
}
return ans;
}
} t;
int a[maxn], s[maxn], p[maxn], ans[maxn];
int cnt[maxn]; // 本来想用map统计的,结果发现统计s就够了
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, len = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
s[i] = t.ask(a[i] - 1) + 1;
t.add(a[i], s[i]);
len = max(len, s[i]);
}
t.clear();
for (int i = n; i; i--) {
int num = maxn - a[i] + 1;
p[i] = t.ask(num - 1) + 1;
t.add(num, p[i]);
}
for (int i = 1; i <= n; i++) {
if (s[i] + p[i] - 1 < len) ans[i] = 1;
else cnt[s[i]]++;
}
for (int i = 1; i <= n; i++) {
if (s[i] + p[i] - 1 < len) continue;
if (cnt[s[i]] > 1) ans[i] = 2;
else ans[i] = 3;
}
for (int i = 1; i <= n; i++) cout << ans[i];
return 0;
}
posted on 2025-09-01 05:01 LDJ_Phigros 阅读(5) 评论(0) 收藏 举报
浙公网安备 33010602011771号