马蹄集 oj赛(双周赛第二十八次)

目录

AB数对

一样的虫子

黑客小码哥

大约

合并石子

来给单词分类

事务处理

前k小数(进阶)

前K小数

修建传送带

第k小函数值

权值计算


AB数对


少难度:黄金·时间限制:1秒四占用内存:128 M
给出一串数以及一个数字C,要求计算出所有A-B=℃的数对的个数,
格式
输入格式:输入共两行,第一行两个整数 n,C(1≤n≤200000,1≤C≤30);第二行 n 个整数,作为要求处理的那串数。
输出格式:一行表示该串数中包含的满足 A- B=℃ 的数对的个数。
样例 1

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 +7;
int n,c,a[N];
long long ans;
map<int,int>mp;

int main() {
    cin >>n >>c;
    for (int i=1;i<= n;i ++){
        cin>>a[i];
        mp[a[i]]++;
        a[i]-= c;
    }
    for(int i=1;i<=n;i++)
        ans += mp[a[i]];
    cout <<ans <<endl;
    return 0;
}

一样的虫子


难度:黄金。时间限制:1秒巴占用内存:128 M
有N只虫子,每只虫子有6条腿,每条腿都有长度而且长得很奇怪,如图所示:
从任何一条腿开始顺时针或逆时针往后记录长度,得到的六元组都代表形状相同的虫子。例如 a1,Q2,·..,6和 a2,Q3,…….,6,a1就是形状相同的虫子; a1,Q2,·…·,a6和 a6,a5,.,a1也是相同的虫子。
我们称两只虫子相同,当且仅当它们各自从某一条腿开始顺时针或逆时针记录长度,能得到两个相同的六元组。
小码哥请你计算这N只虫子中是否存在两只相同的虫子。
格式
输入格式:输入的第一行将包含一个整数 n,即要检查的虫子的数量;接下来是 n行,每行描述一个虫子。
每只虫子将由包含六个数 a1,a2,·..,a6 的行来描述,即虫子腿的长度,

//
// Created by felix on 2024/6/13.
//
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e5 +3;
const int N = 1e5 + 3;
struct NODE {
    int val[6],next;
}insect[N];
int n,h[N],idx;

int F(int *a) {
    long long sum = 0,pro = 1;
    for(int i=0;i < 6;i++) {
        sum=(sum+a[i])% mod;
        pro = pro*a[i]%mod;
    }
    return (sum + pro)%mod;
}
    bool equal(int *a,int *b){
    for(int i=0;i<6;i++) {
        for (int j=0;j<6;j++){
            bool flag = true;
            for (int k =0;k < 6;k++) {
                if(a[(i+k)%6] != b[(j+k)%6])
                    flag = false;
            }
            if (flag)
                return true;
            flag = true;
            for (int k = 0;k < 6;k++){
                if(a[(i+k)%6] != b[(j-k+6)%6])
                    flag = false;
            }
            if (flag)
                return true;
        }
    }
        return false;
    }
    bool find(int *a) {
    int k = F(a);
    for (int i=h[k]; i !=-1;i = insect[i].next)
        if (equal(insect[i].val,a))
            return true;
    return false;
}
    void insert(int *a) {
    int k = F(a);
    memcpy(insect[idx].val,a,6 * sizeof(int));
    insect[idx].next = h[k];
    h[k]= idx;
    idx++;
}
        int main(){
            memset(h,-1,sizeof h);
            cin >> n;
            while (n--){
                int a[6];
                for (int i=0;i<6;i++)
                    cin >> a[i];
                if (find(a)){
                    cout << "found.";
                    return 0;
                }else
                    insert(a);
            }
    cout <<"No";
    return 0;
}

黑客小码哥


难度:黄金时间限制:1秒四占用内存:256M
小码哥是一名黑客,他最近刚彩票中奖,由于还没兑换,小码哥十分担心彩票被盗(小码哥过分谨慎了),他想为自己的保险箱设新的密码,顺便他想让你测试编码。
现有两种编码方式:
1.对于已知字符串中的某种字符,全部变成另一种字符。如里面出现的A全部换成B;2.对于当前字符串,打乱字符顺序。
先给你一个加密后的字符串和加密前的字符串,判断加密前的字符串是否能得到加密后的字符串。字符串中字符均为大写字母。
格式

/*
    MT2128 黑客小码哥 
        
*/
 
#include<bits/stdc++.h> 
using namespace std;
 
const int LETERCNT = 26;
 
// 判断两个字符串是否有可能是经过指定加密算法处理前后的两串 
bool isSamePossiblely(string str1, string str2){
    
    // 长度不同就一定不是
    int strlen = str1.length();
    if(strlen != str2.length()) return false; 
    
    // 否则进一步判断各字符的出现次数是否一致
    int ary1[LETERCNT]={0}, ary2[LETERCNT]={0};
    
    // 先统计各字符串中不同字符的出现次数(即认为存在字符变换操作)
    for(int i=0; i<strlen; i++){
        ary1[str1[i]-'A']++;
        ary2[str2[i]-'A']++;
    }
    
    // 消除字符间的顺序差异(即认为存在字符顺序变换操作)
    sort(ary1, ary1+LETERCNT); 
    sort(ary2, ary2+LETERCNT); 
    
    // 判断是否可能是变换前后的两字符串 
    for(int i=0;i<LETERCNT;i++)
        if(ary1[i] != ary2[i]) 
            return false;
            
    return true;
}
 
int main()
{
    string str1, str2; 
    while(cin>>str1>>str2) {
        if(isSamePossiblely(str1, str2)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    
    return 0;
}

大约


乡难度:钻石时间限制:1秒四占用内存:128 M
给你一个相邻数差不超过1的序列,求最长子串的长度,满足子串中的最大值减最小值也不超过 1。
格式
输入格式:一个正整数 n,然后是长度为 n 的整数序列。
输出格式:一个正整数表示答案。
样例 1

//
// Created by felix on 2024/6/13.
//
#include <bits/stdc++.h>
using namespace std;
const int N=  1e5 + 7;
int n,ans,a[N];
priority_queue<int>max2,maxDel;
priority_queue<int,vector<int>,std::greater<int>>min2,minDel;

int main() {
    cin >>n;
    for(int i=1,j=1;i<=n;i++) {
        cin >> a[i];
        max2.push(a[i]);
        min2.push(a[i]);
        while (max2.top()-min2.top()>1) {
            maxDel.push(a[j]);
            minDel.push(a[j]);
            j++;
            while (maxDel.size() && max2.top() == maxDel.top())
                max2.pop(),maxDel.pop();
            while (minDel.size() && min2.top()==minDel.top())
                min2.pop(),minDel.pop();
        }
        ans = max(ans,i-j+1);
    }
    cout << ans;
    return 0;
}

合并石子


少 难度:钻石。时间限制:1秒四占用内存:128 M
地上有几堆石子,你每次可以合并任意两堆,每一次合并的代价为两堆石子的数量差值的绝对值,问如何合并才能拥有最小代价?
以上问题小码哥当然知道你会,但是小码哥今天心情不错,他为了奖励你,将每一堆石子的初始数量变为了 1,但是n的范围将会到达 1015 ,即1<n<1015
格式
输入格式:多组数据:
第一行输入一个 u ,表示共 w 组数据;每一组数据 输入一个 n。

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

ll w, n, ans;
struct NODE {
    ll num1, num2; // 初始情况下,比如12就是为1,12
    bool operator>(const NODE &a) const { return num1 > a.num1; }
} tmp, tmp2;
priority_queue<NODE, vector<NODE>, greater<NODE>> q;

int main() {
    cin >> w;
    while (w--) {
        ans = 0;
        cin >> n;
        while (!q.empty()) q.pop();
        q.push({1, n});
        while (!(q.size() == 1 && q.top().num2 == 1)) {
            tmp = q.top(); q.pop();
            if (tmp.num2 == 1) {
                tmp2 = q.top(); q.pop();
                ans += tmp2.num1 - tmp.num1;
                q.push({tmp.num1 + tmp2.num1, 1});
                if (tmp2.num2 != 1)
                    q.push({tmp2.num1, tmp2.num2 - 1});
            } else {
                if (tmp.num2 % 2) {
                    q.push({tmp.num1 * 2, tmp.num2 / 2});
                    q.push({tmp.num1, 1});
                } else
                    q.push({tmp.num1 * 2, tmp.num2 / 2});
            }
        }
        cout << ans << endl;
    }
    return 0;
}

来给单词分类


少难度:钻石。时间限制:1秒巴占用内存:128 M
现有如下单词分类原则:两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等,现有几个单词均由大写字母组成,每个单词长度小于等于100。求单词被分为几类
格式
输入格式:第一行输入单词个数n;以下 n 行每行一个单词。
输出格式:一个整数表示类数。

import java.util.Scanner;
import java.util.*;
class Main {
 public static void main(String[] args) {
 
 Scanner input = new Scanner(System.in);
 int n= Integer.parseInt(input.next());
 
 Set<String> a=new HashSet<>();
 
 for (int i = 0; i < n; i++) {
 char[] ch=input.next().toCharArray();
 int[] b=new int[26];
 for (int j = 0; j < ch.length; j++) {
 b[ch[j]-'A']++;
 }
 a.add(Arrays.toString(b));
 }
 System.out.println(a.size());
 input.close();
 }
}
 

事务处理


少 难度:钻石 时间限制:1秒巴 占用内存:128 M
小码哥有n件事需要处理,每件事有编号ai,到来的时间t,需要占用的时间,,优先级”;其中优先级用自然数表示,数字越大,则优先级越高。
如果一件事情到达的时候小码哥是空闲的,那么小码哥会一直做,直到做完这件事,除非在这个过程中,有一件比它优先级高的事情要干。在这种情况下,这件新的(优先级更高的)事情会被小码哥去处理,而原先的只有等待处理。
如果一件事情到达时,小码哥正在处理一件比它优先级高或优先级相同的事情,则这件(新到达的)必须等待。一旦小码哥空闲下来,则选择优先级最高的先处理。如果有多件优先级最高的事情,则选择到达时间最早的。
小码哥在第 工 秒收到了一件在所有待办事情中优先级最高的事情时,他最快只能在第工+1秒开始这件事

//
// Created by felix on 2024/6/14.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 15007;
struct NODE {
    int ai,ti,fi,vi;
    bool operator<(const NODE &b) const {
        if (vi ==b.vi)
            return ti > b.ti;
        return vi < b.vi;
    }
}tmp,p[N];
priority_queue<NODE,vector<NODE>,less<NODE>>q;
int now,cnt = 1;
int main(){
    while (cin >>p[cnt].ai >>p[cnt].ti >>p[cnt].fi >>p[cnt].vi)
        cnt++;
    cnt--;
    q.push(p[1]);
    now = p[1].ti;
    for (int i=2;i<=cnt;i++){
        while (!q.empty()&&p[i].ti >now +q.top().fi){
            now += q.top().fi;
            cout <<q.top().ai <<" "<<now <<endl;
            q.pop();
        }
        if (!q.empty()){
            tmp = q.top(),q.pop();
            tmp.fi -= p[i].ti-now;
            q.push(tmp);
        }
        q.push(p[i]);
        now = p[i].ti;
    }
    while (!q.empty()) {
        tmp =q.top(),q.pop();
        cout << tmp.ai <<" "<<now + tmp.fi <<endl;
        now+= tmp.fi;
    }
        return 0;
    }

前k小数(进阶)


·难度:黄金 时间限制:1秒四占用内存:128 M
给你几 个长度为m 的己知数列,你一次可以从每个数列中选出一个元素,共几个数,将这n个数的和,放入a数组中,穷举所有的选数可能,并且都放入a数组中。
小码哥请你计算a数列中前k小数是多少?
格式
输入格式:输入n,m,k;
接下来 几 行,每一行 m 个数,空格分隔,一行表示一个数列,共n 行。
输出格式:从小到大输出前 k小的数。

//
// Created by abner on 2023/5/10.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 1e8 + 7;
int n,m,k,a[N],b[N],c[N];
struct NODE {
    int ida, idb, num;
 
    bool operator>(const NODE &a) const { return num > a.num; }
}tmp;
priority_queue<NODE,vector<NODE>,greater<NODE>>q;
int main(){
    cin>>n>>m>>k;
    for (int i=1;i <=m;i++)
        cin >>a[i];
    for (int i = 1;i<=m;i++)
    cin >>b[i];
    sort(a + 1,a + m + 1);
    sort(b+1,b+m+1);
    for (int i = 1;i<=m;i++)
    q.push({i,1,a[i]+b[1]});
    for (int i = 1;i<=k;i++) {
        tmp = q.top(), q.pop();
        c[i] = tmp.num;
        tmp.num = a[tmp.ida] + b[++tmp.idb];
        q.push(tmp);
    }
    n-=2;
    while (n--){
        while (!q.empty())
            q.pop();
    for (int i=1;i <= k;i++)
        a[i]=c[i];
    for (int i=1;i <=m;i++)
        cin >>b[i];
    sort(b+1,b+m+1);
    for (int i=1;i <=k;i++)
        q.push({i,1,a[i]+b[1]});
        for (int i=1;i <=k;i++) {
            tmp = q.top(), q.pop();
            c[i] = tmp.num;
            tmp.num = a[tmp.ida] + b[++tmp.idb];
            q.push(tmp);
        }
        }
        for (int i=1;i<=k;i++)
        cout <<c[i]<<" ";
        return 0;
               }

前K小数


少难度:黄金。时间限制:1秒四占用内存:128 M
小码哥现在手上有两个长度为n 的数列 a,b,(1<i,j<n) 通过 a;+b;可以构造出n*几个数,求构造出的数中前k小的数。
格式
输入格式:第一行 2 个数 n,k;
第二行 n 个数,表示数列 a;
第三行 n 个数,表示数列 b。
输出格式:从小到大输出前 k小的数。

 #include<bits/stdc++.h>
 
 using namespace std;
 const int maxSize = 10100;
 int a[maxSize];
 int b[maxSize];
 struct Node{
 int sum,b;
 Node(int sum,int b):sum(sum),b(b){}
 bool operator < (const Node &b) const{
 return sum>b.sum;
 }
 };
 priority_queue<Node>minList;
 int main(){
 int n,k;
 cin>>n>>k;
 for(int i=0;i<n;i++){
 cin>>a[i];
 }
 for(int i=0;i<n;i++){
 cin>>b[i];
 }
 sort(a,a+n);
 sort(b,b+n);
 for(int i=0;i<n;i++){
 minList.push(Node(a[i]+b[0],0));
 }
 for(int i=0;i<k;i++){
 Node node=minList.top();
 minList.pop();
 cout<<node.sum<<" ";
 int tempB = node.b;
 if(tempB+1<n){
 minList.push(Node(node.sum-b[tempB]+b[tempB+1],tempB+1));
 }
 }
 
 return 0;
 }

修建传送带


难度:黄金。时间限制:2秒四占用内存:128M
小码哥,我需要更多的能量··
小码哥在距离母星系11.4光年的地方发现了一颗地形为贫瘠荒漠的行星,他决定把这块适建区域108%的星球改造成一个巨大的生产基地。
小码哥首先把星球的建造区域分成了几个节点,并记为1,2,..,几号节点,小码哥已经在这些节点放置了工作站,剩下的就是用单向传送带把它们连接起来(小码哥的美学原则是不使用物流塔)。但随着传送带越铺越多,小码哥开始处理不来节点之间的连接关系了,为了确认接下来的铺设方案,小码哥需要知道从某一个节点放置的货物能否随着传送带被送往另一个指定的节点,但小码哥看不懂自己混乱的走线了,于是他决定求助于你。
小码哥的所有行动可以被概况成两条指令

//
// Created by felix on 2024/6/14.
//
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
int nex[N], n, m;
bool step[N];

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        nex[i] = i;
    while (m--) {
        char op;
        int x, y;
        cin >> op >> x >> y;
        if (op == 'A') { // 修改字符比较
            if (nex[y] == x)
                nex[y] = y;
            nex[x] = y;
        } else if (op == 'Q') { // 修改字符比较
            int temp = x;
            memset(step, 0, sizeof(step));
            bool flag = true;
            while (!step[temp]) {
                // 只要这个节点没有遍历过
                if (temp == y) {
                    cout << "Yes" << endl;
                    flag = false;
                    break;
                }
                step[temp] = true;
                temp = nex[temp];
            }
            if (flag)
                cout << "No" << endl;
        }
    }
    return 0;
}

第k小函数值


难度:黄金。时间限制:1秒四占用内存:128 M
小码哥有几个函数,他们都可以写成二次函数的形式,即A*æ*æ+B*æ+C对于不同的“的值这些函数都可以产生许多函数值。小码哥想知道在产生的函数值中第k小的值是什么?即将这几个函数所有可以生成的函数值按非严格升序排序后的第k个元素。x属于正整数即1,十无穷
格式
输入格式:第一行输入两个正整数n和k;
以下 n 行每行三个整数,其中第讠行的三个数分别位 A,B;和 C;。
输出格式:输出第 ん个数。

//
// Created by felix on 2024/6/14.
//
#include <bits/stdc++.h>
using namespace std;
struct NODE{
int ans,a,b,c,x;
bool operator>(const NODE &n)const { return ans > n.ans;}
};
priority_queue<NODE,vector<NODE>,greater<NODE>>q;
int n,k;
int f(int a,int b,int c,int x){return a * x * x + b * x + c;}
int main(){
    cin >>n >>k;
    for(int i=1;i <= n;i++) {
        int a,b,c;
        cin >>a >>b>>c;
        q.push({f(a,b,c,1),a,b,c,1});
    }
        while (k--){
            NODE t = q.top();
            q.pop();
            q.push({f(t.a,t.b,t.c,t.x + 1),t.a,t.b,t.c,t.x + 1});
            if(k==0)
                cout <<t.ans;
        }
        return 0;
    }

权值计算


难度:黄金时间限制:1秒四占用内存:128 M
对于一个长度为n的数组a,我们定义它的权值w。若a中存在数满足在整个数组中出现的次数大于等于 本身,这样的x中最大的一个就是a的权值 a;若不存在这样的 ,则该数组的权值为0。现在小码哥给你一个数组,请你计算它的权值。
格式
输入格式:输入共两行,第一行一个正整数n(n∈[1,1x105]);第二行 n 个以空格隔开的整数,表示数组中的数,它们均在[0,1x105]内。
输出格式:输出该数组的权值。

/*
    MT2127 权值计算 

    map使用技巧:
    当map中的key为基本数据类型时,其默认按key值升序排列
*/

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

// 定义数组最大长度
const int MAX = 100005;

// 变量申明 
int ary[MAX]; 
map<int, int> m; 

// 寻找数组中某元素出现次数大于其本身的最大元素 
int getWeight(int ary[], int n){
    
    // 遍历所有字符串,统计每个数字的出现次数  
    for(int i=0; i<n; i++)
        m[ary[i]]++;
    
    // 遍历 map 寻找最大的出现次数大于其本身的元素(因此这里用的是反向迭代器) 
    for(auto iter = m.rbegin(); iter!=m.rend(); iter++)
        if(iter->second >= iter->first)
            return iter->first;
    
    return 0;
}

int main()
{
    // 录入数据 
    int n; cin>>n; 
    for(int i=0;i<n;i++) cin>>ary[i];
    
    // 输出权值 
    cout<<getWeight(ary, n)<<endl;
    
    return 0;
}
  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
循环比日程表是一种常见的算法问题,可以使用递归或迭代的方式来生成日程表。下面是一个使用C++编写的循环比日程表的示例代码: ```cpp #include <iostream> #include <vector> using namespace std; void generateSchedule(int teams) { if (teams % 2 != 0) { teams++; // 如果队伍数为奇数,添加一个虚拟队伍 } int rounds = teams - 1; // 总轮数 int matches = teams / 2; // 每轮的比 vector<vector<int>> schedule(rounds, vector<int>(matches)); // 初始化第一轮的比安排 for (int i = 0; i < matches; i++) { schedule[0][i] = i + 1; } // 生成后续轮的比安排 for (int round = 1; round < rounds; round++) { for (int match = 0; match < matches; match++) { int team1 = schedule[round - 1][match]; int team2; // 计算每个队伍的对手 if (match == 0) { team2 = teams - 1; } else { team2 = schedule[round - 1][match - 1]; } // 考虑虚拟队伍的情况 if (team1 == teams - 1 || team2 == teams - 1) { team1 = (team1 + 1) % (teams - 1); team2 = (team2 + 1) % (teams - 1); } schedule[round][match] = team2; } } // 打印比日程表 for (int round = 0; round < rounds; round++) { cout << "Round " << round + 1 << ": "; for (int match = 0; match < matches; match++) { cout << schedule[round][match] << " vs " << teams - schedule[round][match] - 1 << " "; } cout << endl; } } int main() { int teams; cout << "Enter the number of teams: "; cin >> teams; generateSchedule(teams); return 0; } ``` 这段代码中,我们首先根据输入的队伍数计算总轮数和每轮的比。然后,使用一个二维向量 `schedule` 来存储比安排。我们从第一轮开始,逐轮生成比对阵,并将结果存储在 `schedule` 中。最后,打印出比日程表。 希望这个示例代码对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值