马蹄集 开学季活动赛

文章介绍了多个编程问题,涉及区间内的最大平均值计算、门票费用抵消策略、二阶前缀和的应用、最大异或和、动态规划解决手链问题、统计重点页数、信号灯修复最少数量、切蛋糕分数优化、矩阵区域计数和队伍排列分析等,均为IT技术中的算法题目。
摘要由CSDN通过智能技术生成

目录

最大的平均值

门票

二阶前缀和

最大异或和

背军理

信号灯

切蛋糕

矩形

矩阵01变

运动会进行中

三连

距离平方和


最大的平均值


黄金时间限制:1秒巴 占用内存:128 M少难度:
给一个数组,长度为n,找一个长度大于等于m的子区间,使这个区间的元素的平均值最大
格式
输入格式:第一行输入整数 n 和 m ,数据间用空格隔开接下来 n 行,每行输入一个整数 ai 。
输出格式:输出一个整数,表示平均值的最大值乘以 1000 再向下取整之后得到的结果

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-6;
const int N=1e5 +10;
int n,m;
double a[N],sum[N],l,r;

int check(double mid){
    double minn =0;
    for (int i=1;i<=n;i++)
        sum[i] = sum[i - 1] + a[i] - mid;
    for(int i=m;i<=n;i++){//假设第i个数是尾巴
        minn = min(minn,sum[i - m]);
        if (sum[i] >= minn)
            return 1;
    }
    return 0;
}
int main(){
    cin >>n >>m;
    for (int i=1;i<=n;i++) {
        cin >> a[i];
        r = max(r, a[i]);
    }
        while (r-l>=eps) {
            double mid = (l + r) / 2;
            if (check(mid))
                l = mid;
            else
                r = mid;
        }
            cout <<(int)(r * 1000)<<endl;
            return 0;
        }

门票


少 难度:钻石 时间限制:1秒巴 占用内存:128 M
小码哥家附近的一个主题公园最近搞了一个活动,小码哥在活动中获得了一等奖。而一等奖是一长串的纸条,上面有几个格子,每个格子里有一个数字,活动人员告诉小码哥,只要他裁下一段连续的格子,格子内数字的总和/裁下的格子的数量大于等于门票费t,那么小码哥就能用这段格子抵消门票费。
小码哥想要尽可能多的利用这个奖品,为此他想先知道有多少种裁剪的方案能裁出一段能抵消门票费的格子。
由于方案数可能很大所以需要你输出方案数对1e9+7取模的结果

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 +7;
const int N = 1e6 + 10;
#define ll long long
ll n,t,a[N],sum[N],ans;
ll q[N];
void merge_sort(int l,int r,ll *a) {
    if (l >= r)
        return;
    int mid = l + r >> 1;
    merge_sort(l, mid, a), merge_sort(mid + 1, r, a);

    int i = l, j = mid + 1, t = 0;
    while (i <= mid && j <= r) {
        if (a[i] <= a[j]) {
            q[t++] = a[j++];
            ans += mid - i + 1;//降序排列,
            //求非逆序数
            ans %= MOD;
        } else
            q[t++] = a[i++];
    }
    while (i <= mid) q[t++] = a[i++];
    while (j <= r) q[t++] = a[j++];
    for (i = l, j = 0; i <= r; i++, j++)
        a[i] = q[j];
}
    int main(){
        cin >>n >>t; 
        for(int i=1;i <= n;i++) {
            cin >> a[i];
            a[i] -= t;
            sum[i] = sum[i - 1] + a[i];
        }
            merge_sort(0,n,sum);
            cout <<ans % MOD;
            return 0;
        }

二阶前缀和


难度:黄金时间限制:1秒巴: 占用内存:128 M
在一个直角坐标系上,有个坐标上有元素值(其余坐标的元素值为0),现给定一些点的坐标(2i,y)和这个坐标的元素值",计算用一个边长为R的正矩形能囊括 坐标的元素值的和的最大值。不包括正方形的边界。
格式
输入格式:输入文件的第一行为两个正整数n和 R;接下来的 n 行每行有3个自然数,分别表示 i,yi,ui。
输出格式:输出文件仅有一个正整数,表示一个正方形最多能囊括地图上的最大的元素值之

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
const int N =1010;
int a[N][N],s[N][N],ans;
using namespace std;
int main() {
    int n, r;
    cin >> n >> r;
    while (n--) {
        int x, y, w;
        cin >> x >> y >> w;
        x++, y++;
        a[x][y] += w;
    }
    for (int i = 1; i <= 1001; i++) {
        for (int j = 1; j <= 1001; j++) {
            s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
        }
    }
    for (int i = r; i <= 1001; i++) {
        for (int j = r; j <= 1001; j++) {
            ans =
                    max(ans, s[i][j] - s[i - r][j] - s[i][j - r] + s[i - r][j - r]);
        }
    }
    cout << ans;
    return 0;
}

最大异或和


难度:黄金 时间限制:2秒巴 占用内存:128 M
给定一串手链,每个珠子被赋予一个价值w;,现要从中截取连续的一段,使得他们的异或和最大(注意,手链还未串上)。
格式
输入格式:第1行包含一个正整数 N;
第 2 行 n 个正整数 wi ,表示珠子价格。
输出格式:一个正整数,输出最大异或和。

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
int n,a[2010],sum[2010],ans =-0x3f3f3f3f;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum[i] = sum[i - 1] ^ a[i];
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
            ans = max(ans, sum[i] ^ sum[j - 1]);
    cout << ans;
    return 0;
}

背军理


难度:黄金 时间限制:1秒巴 占用内存:128 M
天哪天哪,军理有好多知识需要背呀。老师已经在厚厚的军理书上(该书一共有n页)画上了若干重点。我们现在已经知道,第i页有a;个重点。
现在小码哥向你询问了q次,每次询问给定一个闭区间,y,请你输出从第x页开始到第y页结束,这些页数之间一共有多少重点。
格式
输入格式:第一行一个整数n,表示书的总页数(书页码编号从第一页开始)接下来一行输入 n 个整数 a;,表示该页上的老师画的重点个数;接下来一行一个整数q,表示小码哥的询问次数;

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const int N=1e5 + 10;
int n,q,num[N],sum [N];
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> num[i];
        sum[i] = sum[i - 1] + num[i];
    }
    cin >> q;
    int x, y;
    while (q--) {
        cin >> x >> y;
        cout << sum[y] - sum[x - 1] << endl;
    }
    return 0;
}

信号灯


难度:钻石时间限制:1秒巴 占用内存:128 M
小码哥的农场有很多牛,这些牛很聪明,它们想和人一样过马路,于是小码哥给它们修建了马路。但因为牛又不是那么聪明,他们有时会撞坏信号灯,小码哥很苦恼。于是小码哥想请你帮忙算一下最少修好几个信号灯,可以有个编号连续的信号灯?注:共有N个信号灯,编号为1~N,有B个信号灯损坏,给你它们的编号
格式
输入格式:第一行输入三个正整数 N,K,B(1≤B,K≤N);接下来 B 行每行一个整数描述破损的灯的编号。

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const int N=1e5 +10;
int n,k,b,a[N],sum[N],ans = 0x3f3f3f3f;
int main(){
    cin >>n >>k>>b;
    int tmp;
    while (b--){
        cin >>tmp;
        a[tmp] = 1;
    }
    for(int i=1;i<=n;i++)
        sum[i] = sum[i-1] + a[i];
    for (int i=1;i+k-1 <= n;i++)
        ans = min(ans,sum[i +k-1]-sum[i -1]);
    cout <<ans;
    
    return 0;
}

切蛋糕


难度:钻石时间限制:1秒巴 占用内存:128 M
今天是小码哥的生日,家里人买了蛋糕。蛋糕由不同色彩分成了几个相同的部分,每一部分上面的水果都不同。由于小码哥对水果很有研究,他给每个水果都打了分。小码哥希望能吃到最多分数,但他又最多只能吃m块(m<n)。请你帮他从这n小块中找出连续的最多 m 块蛋糕使得其上的总分数最大。
格式
输入格式:第一行两个整数 n,m,意思如题目介绍;第二行 几 个整数,第 i个整数代表第 讠部分的分数。

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 +10;
int m,n,a[N],s[N],q[N],ans =-0x3f3f3f3f;
int main(){
        cin >>n >>m;
for (int i=1;i<=n;i++){
cin >>a[i];
s[i]=s[i-1]+a[i];
}
    deque<int>q;
    for (int i=1;i<=n;i++){
        if (!q.empty()&&q.front()<i-m + 1)
        q.pop_front();
        while (!q.empty() && s[i] < s[q.back()])
        q.pop_back();
        q.push_back(i);
        ans = max(ans,s[i]-s[q.front()]);
    }
    cout << ans;
    return 0;
}

矩形


乡 难度:钻石 时间限制:1秒巴:占用内存:128 M
给定一个 N*M的矩阵,1表示已经占用了,0表示没有被占用,求一个由0构成的矩阵,使其周长最大。
格式
输入格式:第一行两个整数 n,m 含义如上;
接下来 n 行每行 m 个数表示这个矩阵
输出格式:输出一个数,表示最大周长。

//
// Created by abner on 2024/3/6.
//
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> matrix(n, vector<int>(m));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            char ch;
            cin >> ch;
            matrix[i][j] = ch - '0';
        }
    }

    int maxPerimeter = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (matrix[i][j] == 0) {
                for (int x = i; x < n; ++x) {
                    for (int y = j; y < m; ++y) {
                        if (matrix[x][y] == 0) {
                            bool isValid = true;
                            // Check if all cells inside the rectangle are unoccupied
                            for (int a = i; a <= x && isValid; ++a) {
                                for (int b = j; b <= y && isValid; ++b) {
                                    if (matrix[a][b] == 1) {
                                        isValid = false;
                                    }
                                }
                            }
                            if (isValid) {
                                // Calculate perimeter
                                int perimeter = 2 * (x - i + 1) + 2 * (y - j + 1);
                                maxPerimeter = max(maxPerimeter, perimeter);
                            }
                        } else {
                            break;
                        }
                    }
                }
            }
        }
    }

    cout << maxPerimeter << endl;
    return 0;
}

矩阵01变


难度:黄金时间限制:1秒巴 占用内存:128 M
给定一个 N*M的矩阵,由0和1组成。现在请你求出,对于每个点(,y),以(1,1)为左上角,(x,y)为右下角的矩阵中包含多少个1。
例如:
000
010
000
的答案为:
000
0 1 1

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
char a[110][110];
int b[110][110],sum[110][110];
int m,n;
int main(){
    scanf("%d%d",&m,&n);
    for (int i=1;i<=m;++i)
    scanf("%s",a[i]+1);
    for (int i=1;i<=m;i++) {
        for (int j = 1; j <= n; j++) {
            if (a[i][j] == '1')
                b[i][j] = 1;
        }
    }
        for (int i = 1;i<=m;i++){
            for (int j=1;j <= n;j++){
                sum[i][j] =
                sum[i-1][j]+sum[i][j-1] - sum[i-1][j-1]+b[i][j];
            }
        }
    for (int i =1;i<=m;i++){
        for (int j=1;j<=n;j++){
            cout<<sum[i][j]<<" ";
        }
            cout <<endl;
        }
        return 0;
    }

运动会进行中


乡 难度:钻石
时间限制:1.3秒四占用内存:128 M
运动会快到了,小码哥班里组织彩排,小码哥作为体委不得不担当同学排队列的大任
为了让男女分配均匀,小码哥想知道队列中男女生人数一样的子序列(连续的)最多多长。
格式
输入格式:第一行一个正整数n,代表学生的人数,其中:n≤100000;第二行 n 个用空格隔开的数,这些数只能是。或 1,其中:。代表女生,1代表男生。
输出格式:输出一个非负整数,这个数表示在输入数据中最长的一段男女人数相等的子序列

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 +7;
int n,a [N],sum[N],l[N*2],r[N*2],ans;
int main(){
    cin >>n;
    for(int i=1;i<=n;i++) {
        cin >> a[i];
        if (a[i] == 0)//将女生用-1表示,更容易计算前缀和
            a[i] = -1;
        sum[i] = sum[i - 1] + a[i];//前缀和后,寻找相同数字的最远距离
        int tmp = sum[i] + n;//sum[i]的范围是-n到n,矫正下保证为正数
        if (!l[tmp])
            l[tmp] = i;
        else
            r[tmp] = i;
    }
    for (int i=0;i<2 * n;i++)
    ans = max(ans,r[i]-l[i]);
    cout <<ans <<endl;
    return 0;
}

三连


少 难度:钻石时间限制:1秒四 占用内存:128 M
给出一个长度为n的序列,问有多少种方案将序列划分为恰好连续的三段(每个元素都属于某一段),使得每一段的和都相等。
格式
输入格式:第一行:一个整数n;
第二行: n 个整数,表示序列。
输出格式:一个整数表示方案数。

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
int n,a[100005],s,now,ans,tot;//tot三等分点个数
int main(){
    cin >>n;
    for (int i=1;i<=n;i++){
        cin >> a[i];
        s += a[i];
    }
    for (int i=1;i<=n;i++){
        now +=a[i];
        if (now* 3 == s * 2 && i<n)
        ans += tot;
        if (now * 3==s)
        tot++;}
        cout <<ans;
        return 0;
    }

距离平方和


黄金时间限制:1秒巴占用内存:128 M难度:
你有几个点,请编写一个程序,求这n个点的距离的平方和。
格式
输入格式:第一行:-个整数n(0<n<100000)接下来n行:每行两个整数,y,表示该点坐标(-10000 ≤x,y≤
10000)
输出格式:仅一行:所有点的距离的平方和。

//
// Created by abner on 2024/3/6.
//
#include <bits/stdc++.h>
using namespace std;
#define ll long long

ll ans,sx,sy,n;

int main() {
    cin >> n;
    for (int i = 0; i < n; ++i) {
        int x, y;
        cin >> x >> y;
        ans += (n - 1) * (x * x + y * y) - ((x * sx + y * sy) * 2);
        sx += x, sy += y;
    }
    cout << ans;
    return 0;
}

  • 29
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值