2026-01-15

CF

Problem - 1555D - Codeforces

如果要使一个字符串的子串都不是回文
假设第一个是a,第二个不能填a,只能填其他,假设填b,第三个只能c
所以最后结果为abcabcabc
一共有6种排列方法

  • abc
  • acb
  • bac
  • bca
  • cba
  • cab
    所以枚举6种情况找最小回文数即可
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;
int sum[10][N];
int p[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 1, 0}, {2, 0, 1}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    string s;
    cin >> s;
    memset(sum, 0, sizeof sum);
    for (int i = 0; i < 6; i++)
    {
        for (int j = 0; j < n; j++)
        {
            sum[i][j + 1] += sum[i][j] + ((s[j] - 'a') != p[i][j % 3]); // 前缀和,从 1开始
        }
    }
    while (m--)
    {
        int l, r;
        cin >> l >> r;
        int ans = n;
        for (int i = 0; i < 6; i++)
        {
            ans = min(ans, sum[i][r] - sum[i][l - 1]);
        }
        cout << ans << endl;
    }
}

Problem - 1946C - Codeforces(二分好题)(DFS)

注意多测清空!!!

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;
vector<int> e[N];
int cnt;
int n, k;

int dfs(int now,int fa,int x){
    int num = 1;
    for (int i = 0; i < e[now].size();i++){
        int son = e[now][i];
        if(son==fa)
            continue;
        num += dfs(son, now, x);
    }
    if(num>=x){
        cnt++;
        return 0;
    }
    return num;
}

bool check(int x){
    cnt = 0;//注意
    dfs(1, 0, x);
    return cnt >= k+1;
}

void solve()
{
    cin >> n >> k;
    for (int i = 1; i <= n;i++){
        e[i].clear();
    }
    for (int i = 0; i < n-1;i++){//注意是n-1条边
        int u, v;
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    int l = 1, r = n+1;
    while(l+1<r){
        int mid = l + r >> 1;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    cout << l << endl; 
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        solve();
    }
}

Problem - 1875D - Codeforces(dp好题)

\(dp_i​\) 表示删完所有 \(i\) 耗费的最小代价
\(∀j<i,dp_j​←dp_i​+i×(cnt_j​−1)+j\)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 998244353;
const int N=2e5+10;
int dp[5010];

void solve()
{
    int n;
    cin >> n;
    map<int, int> cnt;
    memset(dp, 0x3f, sizeof dp);
    for (int i = 1, x; i <= n;i++){
        cin >> x;
        cnt[x]++;
    }
    int mex = 0;
    while(cnt[mex])
        mex++;
    dp[mex] = 0;
    for (int i = mex; i >= 1;i--){//从后往前
        for (int j = 0; j < i;j++){
            dp[j] = min(dp[j], dp[i] + (cnt[j] - 1) * i + j);
        }
    }
    cout << dp[0] << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        solve();
    }
}
posted @ 2026-01-15 17:42  Seren_blingbling  阅读(0)  评论(0)    收藏  举报