Codeforces Gym 100513

前面这些题都是一些模拟贪心= =描述还都很长。。。

100513I - Sale in GameStore

可以买任意一个游戏,然后可以选任意个加起来价值小于这个游戏的求最多能有几个。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define FIO ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
#define FILEREAD freopen("input.txt", "r", stdin);
const int INF = 0x3f3f3f3f;
const int N = 2001;
const int MOD = 1e9 + 7;

int main()
{
#ifndef ONLINE_JUDGE
    FILEREAD
#endif
    FIO
    int n;
    cin >> n;
    int p[N];
    for (int i = 0; i < n; ++i)
        cin >> p[i];
    if (n == 1) {
        cout << 1 << endl;
        return 0;
    }
    sort(p, p + n);
    int ans = 0, sum = 0;
    for (int i = 0; i < n - 1; ++i) {
        sum += p[i];
        if (sum <= p[n - 1])
            ans = i;
        else
            break;
    }
    cout << ans + 2 << endl;
    return 0;
}
100513F - Ilya Muromets

可以从序列中拿去长度为k的连续区间,然后再从新的序列中拿去长度为k的连续区间,求能拿走的最大和。DP[i][0/1/2]表示第i个前拿了j段的最大值。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 2e5 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;

int n, k;
int a[maxn];
int sum[maxn], dp[maxn][3];

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]), sum[i] = sum[i-1] + a[i];
    if (2 * k >= n)
    {
        printf("%d\n", sum[n]);
        return 0;
    }
    int max1 = 0, max2 = 0;
    dp[0][0] = dp[0][1] = dp[0][2] = 0;
    for (int i = k; i <= n; i++)
    {
        dp[i][1] = max(dp[i-1][1], dp[i-k][0] + sum[i] - sum[i-k]);
        dp[i][2] = max(dp[i-1][2], dp[i-k][1] + sum[i] - sum[i-k]);
    }
    int ans = dp[n][2];
    //printf("%d\n", ans);
    for (int i = 2 * k; i <= n; i++)
        ans = max(ans, sum[i] - sum[i-2*k]);
    printf("%d\n", ans);
    return 0;
100513M - Variable Shadowing

一个变量如果已经定义过,在更深层的括号里面定义编译器会发出警告,给出代码输出警告信息。刚开始用stack做有点麻烦改用手动维护层数。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 2e5 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;

char s[55][55];
int len[55];

vector<pii> pos[30];
map<pii, int> mp;

void clear(int lv)
{
    for (int i = 0; i < 26; i++)
        while (pos[i].size() && mp[MP(pos[i][pos[i].size()-1].first, pos[i][pos[i].size()-1].second)] > lv)
            pos[i].erase(pos[i].end()-1);
}

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    int n;
    scanf("%d", &n);
    getchar();
    for (int i = 1; i <= n; i++)
        gets(s[i] + 1), len[i] = strlen(s[i] + 1);
    int lv = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= len[i]; j++)
            if (s[i][j] == '{')
                lv++;
            else if (s[i][j] == '}')
            {
                lv--;
                clear(lv);
            }
            else if (s[i][j] == ' ') ;
            else
            {
                //printf("%d %d %d\n", i, j, lv);
                int num = s[i][j] - 'a';
                if (pos[num].size())
                {
                    printf("%d:%d: warning: shadowed declaration of %c, the shadowed position is %d:%d\n", i, j, s[i][j], pos[num][pos[num].size()-1].first, pos[num][pos[num].size()-1].second);
                }
                pos[num].push_back(MP(i, j));
                mp[MP(i, j)] = lv;
            }
    return 0;
}
100513D - Data Center

能量超过所需的情况下尽量让低电压的服务器更少。
贪心模拟,被坑的一题

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

#define FIO ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
#define FILEREAD freopen("input.txt", "r", stdin);
const int INF = 0x3f3f3f3f;
const int N = 200001;
const int MOD = 1e9 + 7;

struct server {
    long long a;
    int l, id;
} s[N];
vector<int> low, high;
int main()
{
#ifndef ONLINE_JUDGE
    FILEREAD
#endif
    FIO
    int n;
    long long m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> s[i].a >> s[i].l;
        s[i].id = i + 1;
    }
    sort(s, s + n, [](server &x, server &y){return x.a > y.a;});
    int r = 0;
    long long sum = 0;
    for (int i = 0; i < n; ++i) {
        sum += s[i].a;
        if (sum >= m) {
            r = i + 1;
            break;
        }
    }
    long long sl = 0, sh = 0;
    for (int i = 0; i < n; ++i)
        if (s[i].l) {
            low.push_back(i);
            sl += s[i].a;
        }
        else
            high.push_back(i);
    int llast = low.size(), hlast = r - llast;
    while (hlast < 0) {
        sl -= s[low[--llast]].a;
        ++hlast;
    }
    for (int i = 0; i < hlast; ++i)
        sh += s[high[i]].a;
    while (sl + sh < m) {
        sl -= s[low[--llast]].a;
        sh += s[high[hlast++]].a;
    }
    cout << r << ' ' << llast << endl;
    for (int i = 0; i < llast; ++i)
        cout << s[low[i]].id << ' ';
    for (int i = 0; i < hlast; ++i)
        cout << s[high[i]].id << ' ';
    return 0;
}
100513G - FacePalm Accounting

修改尽量少让序列的每个长度为K的区间的和都小于0,修改之后不能小于原数组的最小值。首先肯定尽量加在右边最好,然后暴力就行了。虽然最坏的时候他要跑k-1次才能减,但是均摊下来就可以了。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 2e5 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;

LL a[maxn];

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    int n, k;
    LL mmin = INF;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]), mmin = min(mmin, a[i]);
    LL sum = 0, ans = 0;
    for (int i = 1; i < k; i++)
        sum += a[i];
    for (int i = k; i <= n; i++)
    {
        sum += a[i];
        sum -= a[i-k];
        if (sum >= 0)
        {
            ans += sum + 1;
            LL t = sum + 1;
            int now = i;
            while (t)
            {
                LL sub = min(t, a[now]-mmin);
                a[now] -= sub;
                t -= sub;
                now--;
            }
            sum = -1;
        }
    }
    printf("%lld\n", ans);
    for (int i = 1; i <= n; i++)
        printf("%lld ", a[i]);
    puts("");
    return 0;
}
100513E - Election of a Mayor

所有选区有对面的得票和自己的得票,需要自己赢的选区超过总选区的一半才能胜利,可以合并相邻的两个选区,但是合并之后的选区不能再合并,求要合并多少个选区才能赢。
贪心的合并就行了,只要能增加一个获胜的选区或者减少一个失败的选区就可以合并,这样合并出来一定是最佳的,然后选出一些输出就行了。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 2e5 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;

int n;
int m[maxn], r[maxn];

int main()
{
    //freopen("H:\\in.txt","r",stdin);
    //freopen("H:\\out.txt","w",stdout);
    scanf("%d", &n);
    int win = 0;
    for (int i = 0; i < n; i++)
    {
        scanf("%d%d", &m[i], &r[i]);
        if (m[i] > r[i]) win++;
    }
    vector<pii> ans;
    for (int i = 1; i < n; i++)
    {
        int w = 0;
        if (m[i] > r[i]) w++;
        if (m[i-1] > r[i-1]) w++;
        if (w == 1)
        {
            if (m[i] + m[i-1] > r[i] + r[i-1])
            {
                ans.push_back(MP(i-1, i));
                i++;
            }
        }
        if (w == 0)
        {
            ans.push_back(MP(i-1, i));
            i++;
        }
    }

    if (n - (2 * win - 1) > (int)ans.size())
    {
        puts("-1");
        return 0;
    }
    else
    {
        printf("%d\n", max(0, n - (2 * win - 1)));
        for (int i = 0; i < n - (2 * win - 1); i++)
            printf("%d %d\n", ans[i].first + 1, ans[i].second + 1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值