CodeM 2017美团点评编程大赛资格赛

音乐研究

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

美团外卖的品牌代言人袋鼠先生最近正在进行音乐研究。他有两段音频,每段音频是一个表示音高的序列。现在袋鼠先生想要在第二段音频中找出与第一段音频最相近的部分。

具体地说,就是在第二段音频中找到一个长度和第一段音频相等且是连续的子序列,使得它们的 difference 最小。两段等长音频的 difference 定义为:
difference = SUM(a[i] - b[i])2 (1 ≤ i ≤ n),其中SUM()表示求和
其中 n 表示序列长度,a[i], b[i]分别表示两段音频的音高。现在袋鼠先生想要知道,difference的最小值是多少?数据保证第一段音频的长度小于等于第二段音频的长度。
输入描述:
第一行一个整数n(1 ≤ n ≤ 1000),表示第一段音频的长度。
第二行n个整数表示第一段音频的音高(0 ≤ 音高 ≤ 1000)。
第三行一个整数m(1 ≤ n ≤ m ≤ 1000),表示第二段音频的长度。
第四行m个整数表示第二段音频的音高(0 ≤ 音高 ≤ 1000)。
输出描述:
输出difference的最小值
输入例子1:
2
1 2
4
3 1 2 4

输出例子1:
0
#include 
using namespace std;

#define inf 0x3f3f3f3f
int N, M;
int a[1010], b[1010];

int main() {
    scanf("%d", &N);
    for(int i = 0; i < N; i ++) scanf("%d", &a[i]);
    scanf("%d", &M);
    for(int i = 0; i < M; i ++) scanf("%d", &b[i]);
    int ans = inf;
    for(int i = 0; i <= M - N; i ++) {
        int sum = 0;
        for(int j = 0; j < N; j ++) {
            sum += (b[i + j] - a[j]) * (b[i + j] - a[j]);
        }
        ans = min(ans, sum);
    }
    printf("%d\n", ans);
    return 0;
}
View Code

 

锦标赛

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

组委会正在为美团点评CodeM大赛的决赛设计新赛制。

比赛有 n 个人参加(其中 n 为2的幂),每个参赛者根据资格赛和预赛、复赛的成绩,会有不同的积分。比赛采取锦标赛赛制,分轮次进行,设某一轮有 m 个人参加,那么参赛者会被分为 m/2 组,每组恰好 2 人,m/2 组的人分别厮杀。我们假定积分高的人肯定获胜,若积分一样,则随机产生获胜者。获胜者获得参加下一轮的资格,输的人被淘汰。重复这个过程,直至决出冠军。

现在请问,参赛者小美最多可以活到第几轮(初始为第0轮)?
输入描述:
第一行一个整数 n (1≤n≤ 2^20),表示参加比赛的总人数。
接下来 n 个数字(数字范围:-1000000…1000000),表示每个参赛者的积分。
小美是第一个参赛者。
输出描述:
小美最多参赛的轮次。
输入例子1:
4
4 1 2 3
输出例子1:
2
#include 
using namespace std;

int N, st;
int minn = 0, ans = 0;

int main() {
    scanf("%d", &N);
    scanf("%d", &st);
    for(int i = 1; i < N; i ++) {
        int x;
        scanf("%d", &x);
        if(x <= st) minn ++;
    }
    if(!minn) ans = 0;
    else ans = ((int)(log(minn * 1.0) / log(2.0)));
    
    printf("%d\n", ans);
    
    return 0;
}
View Code

 

优惠券

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

美团点评上有很多餐馆优惠券,用户可以在美团点评App上购买。每张优惠券有一个唯一的正整数编号。当用户在相应餐馆就餐时,可以在餐馆使用优惠券进行消费。优惠券的购买和使用按照时间顺序逐行记录在日志文件中,运营人员会定期抽查日志文件看业务是否正确。业务正确的定义为:一个优惠券必须先被购买,然后才能被使用。

某次抽查时,发现有硬盘故障,历史日志中有部分行损坏,这些行的存在是已知的,但是行的内容读不出来。假设损坏的行可以是任意的优惠券的购买或者使用。

现在问这次抽查中业务是否正确。若有错,输出最早出现错误的那一行,即求出最大s,使得记录1到s-1满足要求;若没有错误,输出-1。
输入描述:
m 分别表示 m (1 ≤ m ≤ 5 * 10^5) 条记录。
下面有m行,格式为:
I x (I为Input的缩写,表示购买优惠券x);
O x(O为Output的缩写,表示使用优惠券x);
? (表示这条记录不知道)。
这里x为正整数,且x ≤ 10^5 。
输出描述:
-1 或 x(1 ≤ x ≤ m) 其中x为使得1到x-1这些记录合法的最大行号。
输入例子1:
0
1
O 1
2
?
O 1
3
I 1
?
O 1
2
I 2
O 1
输出例子1:
-1
1
-1
-1
2
#include 
using namespace std;

const int maxn = 1e6 + 10;
int N;
int vis[maxn];

int main() {
    while(~scanf("%d", &N)) {
        set<int> t;
        set<int>::iterator it;
        string s;
        int x, ans = -1;
        bool flag = false;
        for(int i = 1; i <= N; i ++) {
            cin >> s;
            if(s[0] == '?') t.insert(i);
            else if(s[0] == 'I') {
                scanf("%d", &x);
                if(flag) continue;
                if(vis[x] > 0) {
                    it = t.lower_bound(vis[x]);
                    if(it != t.end()) t.erase(it ++);
                    else {
                        if(!flag) {
                            flag = true;
                            ans = i;
                        }
                    }
                }
                vis[x] = i;
            } else {
                scanf("%d", &x);
                if(flag) continue;
                if(vis[x] <= 0) {
                    it = t.lower_bound(-vis[x]);
                    if(it != t.end()) t.erase(it ++);
                    else {
                        if(!flag) {
                            flag = true;
                            ans = i;
                        }
                    }
                }
                vis[x] = -i;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

 

你可能感兴趣的:(CodeM 2017美团点评编程大赛资格赛)