2025牛客寒假算法基础集训营2题解

C.字符串外串

由D题所知,当长度为K的字符串的头尾在其前后出现过,可爱度即可为K,那么很容易构造出以下序列:{a....z}(长度为n-m的不重复序列){a....z}(a到z的循环);那么在只考虑字符串头(即字母a)在前方出现且位于下标n-m+1的位置,同理考虑字符串尾在后方出现可构造以下序列:{a..z}(a到z的循环){a...z}(长度为n-m的不重复序列),当头部可以满足可爱度为K后,尾部只要不超过K即可所以尾部{a...z}的长度只要小于等于n-m即可,那么通过取余可以快速解决

#include <bits/stdc++.h>  
  
#define lowbit(x) ((x)&(-x))  
#define all(x) x.begin(),x.end()  
#define int long long  
using namespace std;  
const int N = 2e5 + 10;  
const int MOD = 998244353;  
  
void solve() {  
    int n, m;  
    cin >> n >> m;  
    if (n == m || n - m > 26) {  
        cout << "NO\n";  
        return;  
    }  
    cout << "YES\n";  
    for (int i = 0; i < n; i++) {  
        cout << (char) ('a' + i % (n - m));  
    }  
    cout <<'\n';  
}  
  
signed main() {  
    cin.tie(0);  
    cout.tie(0);  
    ios::sync_with_stdio(0);  
    int _ = 1;  
    cin >> _;  
    while (_--) {  
        solve();  
    }  
    return 0;  
}

D. 字符串里串

当存在字符串ab=a...b时,即可满足前面连续后面连续,例如有字符串abcdedcds时,
abcd=ab(cded)cd合法,那么abcd=abc(dedc)d一定也合法,即可得到只要长度为k的字符串的最后一个字符在后面的字符串中出现过即可构成合法的相等连续与不连续子串,同理第一个字符在前面出现也可以。(注意非连续子串最少长度要为2)。

#include <bits/stdc++.h>  
  
#define lowbit(x) ((x)&(-x))  
#define all(x) x.begin(),x.end()  
#define int long long  
using namespace std;  
const int N = 2e5 + 10;  
const int MOD = 998244353;  
  
vector<int> lst(30);          //字符最后一次出现位置  
vector<int> fst(30);          //字符第一次出现位置  
  
void solve() {  
    int n;  
    cin >> n;  
    string s;  
    cin >> s;  
    s = ' ' + s;  
    for (int i = 1; i <= n; i++) {  
        if (!fst[s[i] - 'a']) {  
            fst[s[i] - 'a'] = i;  
        }  
        lst[s[i] - 'a'] = i;  
    }  
    int ans = 0;  
    for (int i = 1; i <= n; i++) {  
        if (lst[s[i] - 'a'] > i) ans = max(ans, i);  
        if (fst[s[i] - 'a'] < i) ans = max(ans, n - i + 1);  
    }  
    if (ans == 1) ans = 0;  
    cout << ans << '\n';  
}  
  
signed main() {  
    cin.tie(0);  
    cout.tie(0);  
    ios::sync_with_stdio(0);  
    int _ = 1;  
//    cin >> _;  
    while (_--) {  
        solve();  
    }  
    return 0;  
}

H.一起画很大的圆!

三个点越接近直线画出的圆越大,那么就找较长的边取最直的线即可

#include <bits/stdc++.h>

#define lowbit(x) ((x)&(-x))
#define all(x) x.begin(),x.end()
#define int long long
using namespace std;
const int N = 2e5 + 10;
const int MOD = 998244353;

void solve() {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    if (abs(a - b) > abs(c - d)) {
        cout<< a  << ' ' << c + 1 << '\n';
        cout<< b - 1  << ' ' << c << '\n';
        cout << b  << ' '<< c << '\n';
    } else {
        cout<< a  << ' ' << c << '\n';
        cout<< a  << ' ' << c + 1 << '\n';
        cout<< a + 1  << ' ' << d << '\n';
    }
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    int _ = 1;
    cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

E.一起走很长的路!

若存在一块牌a[i]>pre[i1],那么只需将第一块牌重量加上a[i]pre[i1]即可,所以若要使所有的牌都可以倒下,让第一块牌加上max(a[i]pre[i1]),(i(1,n))的最大值即可,那么保证所有牌均可倒下。那么如何满足[l,r]的牌可以倒下呢,即满足a[l]+max(a[i]pre[i1]pre[l1]),(i(l+1,r))即可,公式也可以变为a[l]+max(a[i]pre[i1])+pre[l1],(i(l+1,r))il开始是因为第一块牌总能倒下。
(其中最大值用st表处理即可)

#include <bits/stdc++.h>  
  
#define lowbit(x) ((x)&(-x))  
#define all(x) x.begin(),x.end()  
#define int long long  
using namespace std;  
const int N = 2e5 + 10;  
const int MOD = 998244353;  
  
vector<int> a(N), pre(N), d(N);  
  
vector<vector<int>> st(N, vector<int>(30));  
  
void build(int n) {  
    for (int j = 1; (1 << j) <= n; j++) {  
        for (int i = 1; i + (1 << j) - 1 <= n; i++) {  
            st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);  
        }  
    }  
}  
  
int find(int l, int r) {  
    int k = log2(r - l + 1);  
    return max(st[l][k], st[r - (1 << k) + 1][k]);  
}  
  
void solve() {  
    int n, q;  
    cin >> n >> q;  
    for (int i = 1; i <= n; i++) {  
        cin >> a[i];  
        d[i] = a[i] - pre[i - 1];  
        pre[i] = a[i] + pre[i - 1];  
        st[i][0] = d[i];  
    }  
    build(n);  
    while (q--) {  
        int l, r;  
        cin >> l >> r;  
        if (l == r) {  
            cout << 0 << '\n';  
            continue;  
        }  
        cout << max(0ll, find(l , r) + pre[l - 1]) << '\n';  
    }  
}  
  
signed main() {  
    cin.tie(0);  
    cout.tie(0);  
    ios::sync_with_stdio(0);  
    int _ = 1;  
//    cin >> _;  
    while (_--) {  
        solve();  
    }  
    return 0;  
}
posted @   yoez123  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示