第二场选拔赛

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenzhenyu123456/article/details/65638075

A
目测一道难题,十有八九我也不会。

B
思路:枚举圆。
PS:写几何的时候注意精度。

C
思路:首先枚举种类,然后用隔板法求组合数。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL C[30][30];
int main()
{
    for(int i = 0; i <= 25; i++) {
        C[i][0] = 1;
    }
    for(int i = 1; i <= 25; i++) {
        for(int j = 1; j <= i; j++) {
            C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
        }
    }
    int n, k; scanf("%d%d", &n, &k);
    LL ans = 0;
    for(int i = 1; i <= min(n, k); i++) {
        ans += C[n][i] * C[k - 1][i - 1];
    }
    printf("%lld\n", ans);
    return 0;
}

D
思路:贪心。优先选择价值大的,使用的时间尽量靠后。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
pii a[MAXN];
bool cmp(pii x, pii y) {
    return x.second != y.second ? x.second > y.second : x.first < y.first;
}
vector<int> G;
int main()
{
    int n; scanf("%d", &n);
    int MT = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i].first);
        MT = max(MT, a[i].first);
    }
    G.clear();
    for(int i = 1; i <= MT; i++) G.push_back(i);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i].second);
    }
    sort(a + 1, a + n + 1, cmp);
    int ans = 0;
    for(int i = 1; i <= n; i++) {
        if(G.size() == 0) continue;
        if(*G.begin() > a[i].first) continue;

        ans += a[i].second;
        vector<int> :: iterator it;
        it = G.end(); --it;
        if(*it <= a[i].first) {
            G.erase(it);
        }
        else {
            it = upper_bound(G.begin(), G.end(), a[i].first);
            G.erase(--it);
        }

    }
    printf("%d\n", ans);
    return 0;
}

E
思路: KMP 即可。 fail[i] 表示第 i 位前面的最长匹配前缀和后缀。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
char str[MAXN];
int fail[MAXN];
void getfail(char *P) {
    fail[0] = 0; fail[1] = 0;
    for(int i = 1; P[i]; i++) {
        int j = fail[i];
        while(j && P[i] != P[j]) {
            j = fail[j];
        }
        fail[i + 1] = P[i] == P[j] ? j + 1 : 0;
    }
}
bool judge(int l1, int r1, int l2, int r2) {
    int j = 0;
    for(int i = l1; i <= r1; i++) {
        while(j && str[i] != str[l2 + j]) {
            j = fail[j];
        }
        if(str[i] == str[l2 + j]) {
            j++;
        }
        if(j == r2 - l2 + 1) return true;
    }
    return false;
}
int main()
{
    int t; scanf("%d", &t);
    while(t--) {
        scanf("%s", str);
        getfail(str);
        int len = strlen(str);
        int j = fail[len];
        int ans = 0;
        while(j) {
            if(3 * j <= len && judge(j, len - j - 1, 0, j - 1)) {
                ans = j; break;
            }
            else {
                j = fail[j];
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

F
思路: dp1[i] 表示以 a[i] 结尾的最大区间和, dp2[i] 表示以 a[i] 开头的最大区间和。
答案就是 max1<=i+2<=n(dp1[i]+(maxi+2<=j<=ndp2[j]))

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 10;
const int INF = -1e8;
int a[MAXN];
int dp1[MAXN], dp2[MAXN];
int Max[MAXN];
int main()
{
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for(int i = 0; i <= n + 1; i++) {
        dp1[i] = dp2[i] = Max[i] = INF;
    }


    for(int i = 1; i <= n; i++) {
        dp1[i] = max(dp1[i - 1] + a[i], a[i]);
    }
    for(int i = n; i >= 1; i--) {
        dp2[i] = max(dp2[i + 1] + a[i], a[i]);
        Max[i] = max(Max[i + 1], dp2[i]);
    }

    int ans = INF;
    for(int i = 1; i <= n - 2; i++) {
        ans = max(dp1[i] + Max[i + 2], ans);
    }
    printf("%d\n", ans);
    return 0;
}

G
解法一:先二分最小的最大值 Max ,然后选择所有的不大于 Max1 的元素,之后不够的话补上 Max 即可。
解法二:直接用堆去维护,最多入队 2N 个元素。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
int a[MAXN], b[MAXN];
int n;
LL Work(int o) {
    LL ans = 0;
    for(int i = 1; i <= n; i++) {
        if(b[1] + a[i] > o) {
            break;
        }
        int pos = upper_bound(b + 1, b + n + 1, o - a[i]) - b - 1;
        ans += pos;
    }
    return ans;
}
int ans[MAXN], top;
void Put(int o) {
    top = 0;
    for(int i = 1; i <= n; i++) {
        if(b[1] + a[i] > o) {
            break;
        }
        int pos = upper_bound(b + 1, b + n + 1, o - a[i]) - b - 1;
        for(int j = 1; j <= pos; j++) {
            ans[top++] = a[i] + b[j];
        }
    }
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for(int i = 1; i <= n; i++) {
        scanf("%d", &b[i]);
    }
    sort(a + 1, a + n + 1);
    sort(b + 1, b + n + 1);

    int l = a[1] + b[1], r = a[n] + b[n];
    int Max;
    while(r >= l) {
        int mid = l + r >> 1;
        LL num = Work(mid);
        if(num >= 1LL * n) {
            Max = mid;
            r = mid - 1;
        }
        else {
            l = mid + 1;
        }
    }
    Put(Max - 1);
    int left = n - top;
    for(int i = 0; i < left; i++) {
        ans[top++] = Max;
    }
    sort(ans, ans + top);
    for(int i = 0; i < top; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

H
思路: ni=1a[i]>2max1<=i<=na[i]

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 10;
int a[MAXN];
int main()
{
    int n; scanf("%d", &n);
    int ans = -1;
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    int sum = 0;
    int Max = 0;
    for(int i = 0; i < n; i++) {
        sum += a[i];
        Max = max(Max, a[i]);
        if(sum > 2 * Max) {
            ans = i + 1;
            break;
        }
    }
    printf("%d\n", ans);
    return 0;
}

I
水题不说了。

J
很神奇,答案就是把 N 反过来输出。

K
目测语文阅读理解题目。读懂可以AC

L
最多三个人,很多人看错题意了。随便写都可以过

M
模拟即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e3 + 10;
char str[MAXN];
int num[30];
int main()
{
    int n; scanf("%d", &n);
    scanf("%s", str);
    for(int i = 0; i < 26; i++) num[i] = 0;
    for(int i = 0; str[i]; i++) {
        num[str[i] - 'a']++;
    }
    int ans = 0;
    for(int i = 0; i < 26; i++) {
        while(num[i]) {
            num[i]--;
            for(int j = i + 1; j < 26; j++) {
                if(num[j]) {
                    num[j]--;
                }
                else {
                    break;
                }
            }
            ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/chenzhenyu123456/article/details/65638075