Codeforces Round #340 (Div. 2) (629A,629B,629C(排列组合,动态规划),629D(线段树))

本文深入探讨了CodeForces上一系列编程挑战题目的解题思路与实现,涵盖巧克力分配、聚会邀请、括号序列平衡等多个经典问题。通过动态规划、贪心算法等策略,详细阐述了解决每道题目的关键步骤与复杂度分析,为读者提供了全面的编程思维与实战技巧指南。

Far Relative’s Birthday Cake

题目链接:

http://www.codeforces.com/problemset/problem/629/A

解题思路:

Consider that we have rowi chocolates in the i'th row and coli chocolates in the i'th column.

The answer to the problem would be: . It is obvious that every pair would be calculated exactly once (as we have no more than one chocolate in the same square)

Time Complexity: O(n2)

AC代码:

#include <bits/stdc++.h>
using namespace std;

char a[110][110];

int main(){
    int n;
    while(~scanf("%d",&n)){
        int ans = 0,tmp;
        for(int i = 0; i < n; i++){
            scanf("%s",a[i]);
            tmp = 0;
            for(int j = 0; j < n; j++){
                if(a[i][j] == 'C')
                    tmp++;
            }
            ans += tmp*(tmp-1)/2;
        }
        for(int i = 0; i < n; i++){
            tmp = 0;
            for(int j = 0; j < n; j++){
                if(a[j][i] == 'C')
                    tmp++;
            }
            ans += tmp*(tmp-1)/2;
        }
        printf("%d\n",ans);
    }
    return 0;
}

Far Relative’s Problem

题目链接:

http://www.codeforces.com/problemset/problem/629/B

解题思路:

Consider that we have boyi males in the i'th day of the year and girli females in the i'th day of the year. These arrays can be filled easily when you are reading the input (See the code). Then for the i'th day of the year, we could have 2 * min(boyi , girli) people which could come to the party. The answer would be maximum of this value between all days i (1 ≤ i ≤ 366)

Time Complexity: O(366*n)

AC代码:

#include <bits/stdc++.h>
using namespace std;

struct node{
    char sex[10];
    int a,b;
}no[5005];

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i = 0; i < n; i++)
            scanf("%s%d%d",no[i].sex,&no[i].a,&no[i].b);
        int ans = 0,M,F;
        for(int i = 1; i <= 366; i++){
            M = 0;F = 0;
            for(int j = 0; j < n; j++){
                if(no[j].a <= i && no[j].b >= i){
                    if(no[j].sex[0] == 'M')
                        M++;
                    else
                        F++;
                }
            }
            ans = max(ans,min(M,F));
        }
        printf("%d\n",ans*2);
    }
    return 0;
}

Famil Door and Brackets

题目链接:

http://www.codeforces.com/problemset/problem/629/C

解题思路:

This problem can be solved with dynamic programming:

1. Calculate dpi, j : How many sequences of brackets of length i has balance j and intermediate balance never goes below zero (They form a prefix of a valid sequence of brackets).

2. For the given sequence of length n calculate the resulting balance a and the minimum balance b.

3. Try the length of the sequence added at the beginning c and its balance d. If  - b ≤ d then add dpc, d * dm - n - c, d + a to the answer.

Time complexity: O((n - m)^2)

AC代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MOD = 1e9+7;
ll dp[5005][5005];


int main(){
    ll n,m;
    while(~scanf("%lld%lld",&n,&m)){
        string str;
        cin>>str;
        dp[0][0] = 1;
        for(int i = 1; i <= n-m; i++){
            dp[i][0] = dp[i-1][1];
            for(int j = 1; j <= i; j++){
                dp[i][j] = dp[i-1][j+1]+dp[i-1][j-1];
                dp[i][j] %= MOD;
            }
        }
        int num = 0,minnum = 0;
        for(int i = 0; i < m; i++){
            if(str[i] == '(')
                num++;
            else
                num--;
            minnum = min(minnum,num);
        }
        ll ans = 0;
        for(int i = 0; i <= n-m; i++){
            for(int j = 0; j <= i; j++){
                if(j >= -minnum){
                    if(j+num <= n-m && j+num >= 0){
                        ans += dp[i][j] * dp[n - m - i][j + num] % MOD;
                        ans %= MOD;
                    }
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Babaei and Birthday Cake

题目链接:

http://www.codeforces.com/problemset/problem/629/D

解题思路:

First of all, we calculate the volume of each cake: vi = π × hi × ri2.

Now consider the sequence v1v2v3, ..., vn : The answer to the problem is the maximum sum of elements between all increasing sub-sequences of this sequence. How do we solve this? First to get rid of the decimals we can define a new sequence a1a2a3, ..., an such that 

We consider dpi as the maximum sum between all the sequences which end with ai and

dpi = 

The answer to the problem is: π × maxi = 1ndp[i]

Now how do we calculate  ? We use a max-segment tree which does these two operations: 1. Change the i't member to v2. Find the maximum value in the interval 1 to i.

Now we use this segment tree for the array dp and find the answer.

Consider that a1a2a3, ..., an is sorted. We define bi as the position of ai. Now to fill dpi we find the maximum in the interval [1, bi) in segment and we call it x and we set the bi th index of the segment as ai + x. The answer to the problem would the maximum in the segment in the interval [1,n]

Time complexity: O(nlgn)

AC代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 100005;
const double pi = acos(-1.0);

struct node{
    ll r, h, v;
}no[maxn];
struct node2{
    int l,r;
    ll maxv;
}tree[maxn<<2];
int n,m;
ll d[maxn],b[maxn];

void pushup(int id) {
    tree[id].maxv = max(tree[id<<1].maxv,tree[id<<1|1].maxv);
}

void build(int id,int l,int r){
    tree[id].l = l;
    tree[id].r = r;
    tree[id].maxv = 0;
    if(l == r)
        return ;
    int m = (l + r) >> 1;
    build(id<<1,l,m);
    build(id<<1|1,m+1,r);
}

void update(int id,int l,int r,int val){
    if(tree[id].l >= l && tree[id].r <= r){
        if(tree[id].maxv < d[val]){
            tree[id].maxv = d[val];
        }
        return ;
    }
    int mid = (tree[id].l+tree[id].r)>>1;
    if(l <= mid)
        update(id<<1,l,r,val);
    if(mid < r)
        update(id<<1|1,l,r,val);
    pushup(id);
}

ll query(int id,int l,int r) {
    if(tree[id].l >= l && tree[id].r <= r)
        return tree[id].maxv;
    ll ans = 0;
    int mid = (tree[id].l+tree[id].r)>>1;
    if(l <= mid)
        ans = max(ans, query(id<<1,l,r));
    if(mid< r)
        ans = max(ans, query(id<<1|1,l,r));
    pushup(id);
    return ans;
}

int main(){
    while(~scanf("%d",&n)){
        for(int i = 1; i <= n; i++){
            scanf("%lld%lld",&no[i].r,&no[i].h);
            no[i].v = no[i].r * no[i].r * no[i].h;
            b[i] = no[i].v;
        }
        sort(b+1, b+1+n);
        int m = unique(b+1, b+1+n) - b - 1;

        ll cur = 0,v;
        build(1,1,m);
        for(int i = 1; i <= n; i++) {
            int L = lower_bound(b+1, b+1+m, no[i].v) - b;
                if(L > 1) v = query(1,1,L-1);
                else v = 0;
                d[i] = (v + no[i].v);
                update(1,L,L,i);
                cur = max(cur, d[i]);
        }
        printf("%.9f\n",pi*cur);
    }
    return 0;
}


### 关于 Codeforces Round 839 Div 3 的题目与解答 #### 题目概述 Codeforces Round 839 Div 3 是一场面向不同编程水平参赛者的竞赛活动。这类比赛通常包含多个难度层次分明的问题,旨在测试选手的基础算法知识以及解决问题的能力。 对于特定的比赛问题及其解决方案,虽然没有直接提及 Codeforces Round 839 Div 3 的具体细节[^1],但是可以根据以往类似的赛事结构来推测该轮次可能涉及的内容类型: - **输入处理**:给定一组参数作为输入条件,这些参数定义了待解决的任务范围。 - **逻辑实现**:基于输入构建满足一定约束条件的结果集。 - **输出格式化**:按照指定的方式呈现最终答案。 考虑到提供的参考资料中提到的其他几场赛事的信息[^2][^3],可以推断出 Codeforces 圆桌会议的一般模式是围绕着组合数学、图论、动态规划等领域展开挑战性的编程任务。 #### 示例解析 以一个假设的例子说明如何应对此类竞赛中的一个问题。假设有如下描述的一个简单排列生成问题: > 对于每一个测试案例,输出一个符合条件的排列——即一系列数字组成的集合。如果有多种可行方案,则任选其一给出即可。 针对上述要求的一种潜在解法可能是通过随机打乱顺序的方式来获得不同的合法排列形式之一。下面是一个 Python 实现示例: ```python import random def generate_permutation(n, m, k): # 创建初始序列 sequence = list(range(1, n + 1)) # 执行洗牌操作得到新的排列 random.shuffle(sequence) return " ".join(map(str, sequence[:k])) # 测试函数调用 print(generate_permutation(5, 2, 5)) # 输出类似于 "4 1 5 2 3" ``` 此代码片段展示了怎样创建并返回一个长度为 `k` 的随机整数列表,其中元素取自 `[1..n]` 这个区间内,并且保证所有成员都是唯一的。需要注意的是,在实际比赛中应当仔细阅读官方文档所提供的精确规格说明,因为这里仅提供了一个简化版的方法用于解释概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值