LDJ

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\),然后讨论:

  1. 不存在不同的位数,输出 0
  2. \(n\bmod2=1,k = \lceil n/2\rceil\),这时走两边都一样,答案多加一个 \(k-mini\),要么 \(maxj-k\)
  3. \(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)\)就行
  4. \(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;
}

\[\color{white}你知道的太多了 \]

posted on 2025-09-01 05:05  LDJ_Phigros  阅读(78)  评论(0)    收藏  举报

导航