SMU Autumn 2024 div2 1st

news2024/11/24 12:24:21

文章目录

  • The First Week
  • 一、前言
  • 二、算法
    • 1.逆序对
      • <1>(2024牛客国庆集训派对day2 I)
    • 2.图论
      • <1>(2024牛客国庆集训派对day2 F)
    • 3. 二分
      • <1>(AcWing 102. 最佳牛围栏)
      • <2>(2024牛客国庆集训派对day2 J)
    • 4. dijkstra
      • <1>(牛客小白月赛102 D)
    • 5.BFS算法
      • <1>(Required Length)
  • 三、总结


The First Week

长江后浪推前浪, 浮事新人换旧人。 ————刘斧

一、前言


二、算法

1.逆序对

存在1<=i<j<=n,A[I]>A[j]的有序对叫作逆序对。
一些简单朴素算法的时间复杂度都是O(n*n),包括插入排序冒泡排序等等。
在这里插入图片描述

归并排序

  1. 二分一直二分到只有一个元素为止
  2. 可以想象在二分时,逆序对有以上三种结果,全在左边,全在右边,一左一右
  3. 全在左右的都不容易计算,所以继续归并排序
  4. 如果在二分到仅剩一个元素时进行排序,那么当回来计算归并排序时,左右俩边应当是分别排序好的数组
  5. 开始寻找逆序对个数,分别把左右俩个区间的最小值设置成i,j。当找到一个a[i]>a[j]时,前半部分i后面的元素都将与j形成逆序对。
  6. 剩下的没有被扫的元素也得按顺序存入数组b,在最后赋值给a。
int ans = 0;
//储存逆序对个数
void gbsort(int l,int r,int a[]) {
    int mid = (l+r)/2;
    if(l == r) return ;
    //二分到只有一个就终止
    gbsort(l,mid,a);
    gbsort(mid+1,r,a);
    //先计算俩边的逆序对
    int i = l,j = mid+1;
    int k = 0;
    int t = l;
    while(i <= mid && j <= r) {
        if(a[i] > a[j]) {
            ans += (mid+1-i);
            b[t++] = a[j++];
        }
        else b[t++] = a[i++];
    }
    while(i <= mid) b[t++] = a[i++];
    //右边已经跑完了,左边的有剩余
    while(j <= r) b[t++] = a[j++];
    for (int i = l; i <= r; i++) {
        a[i] = b[i];
    }//必须排序
    return ;
}

树状数组

<1>(2024牛客国庆集训派对day2 I)

在这里插入图片描述
依然不是我写的代码,树状数组没太学明白,基本都是抄模版。over。
题解:
给定一个数组a,包括不重复的1到n的数字,可以给任意多个数字加上1,求最小的逆序对数目。
先求出逆序对的个数,然后查找每个数字的位置,如果i+1的位置在i的位置的前面,就把i变成i+1,并跳过i+1的这一个操作。
代码:

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

#define int long long

int n;
int b[200005];

int t[200005]={0};
typedef struct node{
    int val,ind;
}Node;

Node stu[200005];
int Rank[200005];

int lowbit(int x){
    return x&(-x);
}

void add(int pos){
    for(int i=pos;i<=n;i+=lowbit(i)) t[i]+=1;
}

int ask(int pos){
    int ans = 0;
    for(int i=pos;i;i-=lowbit(i)) ans += t[i];
    return ans;
}

int cmp(Node a,Node b){
    if(a.val == b.val) return a.ind<b.ind;
    return a.val<b.val;
}

signed main(){
    int ans = 0;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>stu[i].val;
        b[stu[i].val]=i;
        stu[i].ind = i;
    }
    sort(stu+1,stu+n+1,cmp);
    for(int i=1;i<=n;i++) Rank[stu[i].ind] = i;
    for(int i=1;i<=n;i++){
        int pos = Rank[i];
        ans += ask(n)-ask(pos);
        add(pos);
    }
    //cout<<ans;
    for(int i=1;i<n;i++){
        if(b[i+1]<b[i]) ans--,i++;
    }
    cout<<ans;
    return 0;
}

2.图论

<1>(2024牛客国庆集训派对day2 F)

这题其实不是图论,还是博弈论,但对我们队来说挺崩溃的吧,就还是归在图论板块里了。
Alice和Bob又要玩游戏了…

题解:
给定n个节点m条线的图,可以选择删去一个联通块(不能自成环),或者删去一条线。
找到所有的联通块个数(包括单独点)和成环的联通块(判断环内线段的数目)…反正是一个繁琐且容易出错的思考过程,最后对这个个数判断奇偶。
但是!删边的时候边的数目-1,删联通块的时候,点的个数比边的个数多一,那么就不形成环,所以每次进行操作奇偶都会改变,直接判断点和边的和的奇偶性即可。
代码:
正解的代码真的很简单,我就不放了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=110;
int n,m;
vector<int>a[N];
vector<int>ans;
int dev[N];
bool st[N];
bool vis[N];
int k=0;
int an=1;
int res=0;
bool cmp(int x,int y){
    return x>y;
}
vector<int>b;
void dfs2(int x,int fa){
//     cout<<x<<endl;
    b.push_back(x);
    vis[x]=1;
    if(a[x].size()==1&&a[x][0]==fa) {    
        return;
    }
    for(int i=0;i<a[x].size();i++){
        if(a[x][i]==fa) continue;
        if(vis[a[x][i]]) {
            k=1;
            continue;
        }
        an++;
        dfs2(a[x][i],x);
    }
}
int findf(int x){
    int sumn=0;
    for(int i=0;i<b.size();i++){
        if(!st[b[i]]){
//             cout<<b[i]<<endl;
            for(int j=0;j<a[b[i]].size();j++){
                if(!st[a[b[i]][j]]) sumn++;
            }
        }
    }
    return sumn/2;
}
int find(int x){
    int num=0;
    queue<int>q;
    for(int i=0;i<b.size();i++){
        if(dev[b[i]]==1){
            q.push(b[i]);
            st[b[i]]=1;
            num++;
        }
    }
    while(q.size()){
        int xx=q.front();
        q.pop();
        for(int i=0;i<a[xx].size();i++){
            dev[a[xx][i]]--;
            if(dev[a[xx][i]]==1) {
                num++;
                st[a[xx][i]]=1;
                q.push(a[xx][i]);
            }
        }
    }
//     cout<<findf(x)<<" "<<an-num<<endl;
    return findf(x)-an+num;
}
void solve(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y;
        cin>>x>>y;
        a[x].push_back(y);
        a[y].push_back(x);
        dev[x]++;
        dev[y]++;
    }
    int tip=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            dfs2(i,0);
//             cout<<i<<" "<<an<<endl;
            if(!k){
                b.clear();
                ans.push_back(an);
            }
            else {
//                 cout<<find(i)<<endl;
                res+=find(i);
                tip=1;
            }
            k=0;
            an=1;
        }
    }
//     cout<<res<<endl;
    if((ans.size()+res)%2==0) cout<<"Bob"<<endl;
    else cout<<"Alice"<<endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

3. 二分

<1>(AcWing 102. 最佳牛围栏)

在这里插入图片描述

题解:
N块土地,要求至少F块地的牛的平均值可能的最大值是多少。
代码:

#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
#define endl "\n"
#define PII pair<int,int>
int n,m;
const int N = 1e5+10;
int c[N],sum[N];
double l,r;

bool check(double x) {
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i-1]+c[i]-x;
    }
    double mi = 0;
    for (int i = 0, j = m;j <= n; j++,i++) {
        mi = min(mi,sum[i]);
        if(sum[j]-mi >= 0) return true;
    }return false;
}

void solve() {
    cin >> n >> m;
    l = 0,r = 0;
    for (int i = 1;i <= n; i++) {
        cin >> c[i];
        r = max(r,(double)c[i]);
    }
    while(r-l > 1e-5) {
        double mid = (l+r)/2;
        if(check(mid)) l = mid;
        else r = mid;
    }cout << r*1000 << endl;
    return ;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
 //   cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

<2>(2024牛客国庆集训派对day2 J)

题解:
给定数组a,b,矩阵对应位置大小是a[i]+b[j],要求取出一个行不小于x,列不小于y的矩阵的平均值最大。推算可发现应当要分别找出a,b中连续区间平均值最大的区间。
代码:

#include<bits/stdc++.h>

using namespace std;
#define int long long
#define double long double
int n,m,z,y;
const int N = 1e5+10;
int a[N],b[N];
double sum[N];
double ans;

bool check(double x,int c[],int jx,int n) {
    sum[0] = 0;
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i-1]+c[i]-x;
    }
    double mi = 1e9;
    for (int i = 0,j = jx; j <= n; i++,j++) {
        mi = min(mi,sum[i]);
        if(sum[j]-mi >= 0) return true;
    }return false;
}

void solve() {
    cin >> n >> m >> z >> y;
    double mia=0,maa=0,mib=0,mab=0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        maa=max(maa,(double)a[i]);
    }
    while(maa-mia > 1e-8) {
        double mid = (mia+maa)/2;
        if(check(mid,a,z,n)) mia = mid;
        else maa = mid;
    }
    for (int i = 1; i <= m; i++) {
        cin >> b[i];
        mab=max(mab,(double)b[i]);
    }
    while(mab-mib > 1e-8) {
        double mid = (mib+mab)/2;
        if(check(mid,b,y,m)) mib = mid;
        else mab = mid;
    }
    ans = maa+mab;
    printf("%0.10Lf",ans);
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t = 1;
    //cin >> t;
    while(t--) {
        solve();
    }
    return 0;
}

4. dijkstra

我真的会疯,反正思路还行,dij+dp的感觉,但写起来我真的是框框改。

<1>(牛客小白月赛102 D)

在这里插入图片描述
题解:
tip:花费的时间不要看作边权,当作点权处理。
由于k的范围比较小,在dij的时候记录已经有几次不休息,然后把这次休息和不休息的俩种状态都放进去,如果已经k次不休息,这次必须休息,传入的时候把不休息次数的状态也传入。

代码:

#include<bits/stdc++.h>

using namespace std;
#define int long long
typedef pair<int,int> PII;
const int INF = 1e18;
//不可以写0x3f,这是63,要么就多写几个3f
const int N = 1e6;
int n,m,k;

void solve() {
  //  init();
    int a[N];
    cin >> n >> m >> k;
    vector<int>edge[n+10];
    vector<vector<int>>dist(k+10,vector<int>(n+10,INF));
    vector<vector<int>>vis(k+10,vector<int>(n+10,0));
    //不可以在外面开数组范围N,会内存超限
    //好好学一下怎么开二维数组的大小
 //   int dist[k+1][N+1],vis[][2*N];
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 0; i < m; i++) {
        int u,v;
        cin >> u >> v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    int x = 1;
    priority_queue<pair<int,PII>,vector<pair<int,PII>>,greater<pair<int,PII>>>pq;
    //因为我确实不太会放三个数据,所以就这样放吧
    if(k >= 1) {
        dist[1][1] = 1;
        pq.push({1,{1,1}});
    }//如果是0的话就不能放,因为每次都得休息
    dist[0][x] = a[1];
    pq.push({a[1],{1,0}});
    while(!pq.empty()) {
        x = pq.top().second.first;
        int y = pq.top().second.second;
        int z = pq.top().first;
        pq.pop();
        if(vis[y][x]) continue;
    //    cout << x << ' ' <<dist[0][x] << endl;
        vis[y][x] = 1;
        for (int i = 0; i < edge[x].size(); i++) {
            int next = edge[x][i];
            if(y < k) {
            if(dist[y+1][next] > z+1) {pq.push({z+1,{next,y+1}});
            dist[y+1][next] = min(dist[y+1][next],z+1);}
            }//这次休息
            if(dist[0][next] > z+a[next]) {pq.push({z+a[next],{next,0}});
            dist[0][next] = min(dist[0][next],z+a[next]); }//这次不休息
        } 
    }
    int ans = 1e18;
   // cout << dist[]
    for (int i = 0; i<= k; i++) 
        ans = min(ans,dist[i][n]);
    //已经跑到第n次,休息0到k次的最小距离
    cout << ans << endl;
//    cout << "DA" << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t = 1;
    cin >> t;
    while(t--) solve();
    return 0;
}

5.BFS算法

<1>(Required Length)

在这里插入图片描述

题解:
可以想象原来的数字x,给它分别乘上各个位数,构成了第二层,再继续往下推,直到有任何一个的位数满足要求,就可以返回此时的层数,也就是操作次数了。注意不要多次对相同的数字操作,因为它会有很多相同的数字,可以节约时间。
代码:

#include <iostream>
#include <set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<string.h>
#include<map>
#include<math.h>
#include<stack>

using namespace std;
#define int unsigned long long
int n,x;

vector<int>a[30];
bool st[30];
int ans;
int ms = 100;
typedef pair<int,int> PII;
map<int,bool>mp;

int calc(int x) {
    int res = 0;
    while(x) {
        res++;
        x = x/10;
    }
    return res;
}

int js(int x) {
    int res = 0;
    while(x) {
        res = max(res,x%10);
        x = x/10;
    }
    return res;
}

void bfs() {
    int res = 0;
    queue<PII>q;
    q.push({0,x});
    while(q.size()) {
        int a = q.front().first;
        int b = q.front().second;
        q.pop();
        if(mp[b]) continue;
        mp[b] = true;
        if(calc(b) == n) {
            cout << a << endl;
            return ;
        }
        vector<int>ab;
        int xy = b;
        while(xy) {
            ab.push_back(xy%10);
            xy = xy/10;
        }
        for (auto x : ab) {
            q.push({a+1,b*x});
        }
    }
    return ;
}


void solve() {
    cin >> n >> x;
    ans = 0;
 //   cout << calc(x) << ' ' << js(x) << endl;
    if(calc(x) > n || js(x) == 1) {
        cout << -1 << endl;
        return ;
    }
    else if(calc(x) == n) {
        cout << 0 << endl;
        return ;
    }
    else {
        ans = 0;
        bfs();
 //       cout << ms << endl;
    }
}

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int t=1;
 //   cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

三、总结

累了,不想总结,先这么着吧,题都写不完了已经。
哦不过我写的题还是不止这些的,这些都是我理解了很久的题,就放出来看看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2209115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第17课-C++【模板进阶】

&#x1f307;前言 模板作为搭建STL的关键工具以及泛型编程思想的核心体现&#xff0c;对提高程序灵活性和推动高效迭代开发具有重要意义。除了基本的类型替换功能外&#xff0c;模板还具备如非类型模板参数、全特化、偏特化等高级操作。同时&#xff0c;模板声明与定义不能分…

聚类分析 | AP近邻传播聚类算法

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 AP近邻传播聚类算法 AP&#xff08;Affinity Propagation&#xff09;近邻传播聚类算法是一种基于数据点之间的相似度矩阵来进行聚类的算法。该算法不需要事先设定聚类簇的个数&#xff0c;而是通过在数据点之间传播…

JavaScript 第7章:字符串处理

第7章&#xff1a;字符串处理 在 JavaScript 中&#xff0c;字符串是一个非常常用的数据类型&#xff0c;用于表示文本信息。JavaScript 提供了许多内置的方法来处理字符串&#xff0c;包括操作、搜索、替换和格式化等。 一、字符串操作方法 1. charAt charAt(index) 方法返…

Java面向对象编程--高级

目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习&#xff0c;测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…

基于机器视觉的水果品质检测研究进展

摘 要&#xff1a;水果品质检测关系到水果的包装运输贮藏和销售的效果和收益。传统的外观品质检测主要是利用分级机械&#xff0c;其存在很多不足之处&#xff0c;因此提出了利用机器视觉进行无损检测的技术。利用机器视觉技术主要是检测水果的大小、形状、颜色和表面缺陷四个…

106. 从中序与后序遍历序列构造二叉树【 力扣(LeetCode) 】

文章目录 零、LeetCode 原题一、题目描述二、测试用例三、解题思路四、参考代码 零、LeetCode 原题 106. 从中序与后序遍历序列构造二叉树 一、题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵…

Static修饰不同对象

目录 Static修饰局部变量 Static修饰全局变量 Static修饰函数 Static修饰成员 Static修饰成员变量 Static修饰成员函数 Static修饰成员的特性&#xff1a; 静态成员变量和静态成员函数的使用案例&#xff1a; 案例1&#xff1a;求1 2 3...n 案例2&#xff1a;单例模…

【学术会议投稿链接】React前端框架:构建现代Web应用的强大工具

【即将截稿】第五届经济管理与大数据应用国际学术会议&#xff08;ICEMBDA 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看&#xff1a;https://ais.cn/u/nuyAF3 目录 引言 一、React简介 二、React的核心概念 1. 组件化 2. 虚拟DOM&#xff08;Virtua…

LOID:有效提升遮挡条件下的车道检测精度

1.论文信息 论文标题&#xff1a;LOID: Lane Occlusion Inpainting and Detection for Enhanced Autonomous Driving Systems 作者&#xff1a;Aayush Agrawal, Ashmitha Jaysi Sivakumar, Ibrahim Kaif∗, Chayan Banerjee† 作者单位&#xff1a;印度马德拉斯印度理工学院&…

数学建模算法与应用 第12章 现代优化算法

目录 12.1 粒子群优化算法 Matlab代码示例&#xff1a;粒子群优化算法求解函数最小值 12.2 遗传算法 Matlab代码示例&#xff1a;遗传算法求解函数最小值 12.3 蚁群算法 Matlab代码示例&#xff1a;蚁群算法求解旅行商问题 12.4 Matlab 遗传算法工具 使用遗传算法工具箱…

java的LinkedList

java的LinkedList 什么是LinkedListLinkedList的模拟实现LinkedList的使用ArrayList和LinkedList的区别 什么是LinkedList LinkedList的官方文档 LinkedList的底层是双向链表结构&#xff0c;由于链表没有将元素存储在连续的空间中&#xff0c;元素存储在单独的结点中&#xf…

一维数组的引用

#define SIZE 5 int main(void) { int i 0; int arr[SIZE] { 86,85,85,896,45 };//同理五个数据只是偶然&#xff0c;可能会更多 //输入 for (i 0;i < SIZE;i) { printf("请输入你的第%d个值&#xff1a;",i1); scanf_s(&…

【机器学习】逻辑回归|分类问题评估|混淆矩阵|ROC曲线|AUC指标 介绍及案例代码实现

文章目录 逻辑回归逻辑回归简介逻辑回归的数学基础逻辑回归原理概念损失函数 逻辑回归API函数和案例案例癌症分类预测 分类问题评估混淆矩阵分类评估方法 - 精确率 召回率 F1ROC曲线 AUC指标案例AUC 计算的API分类评估报告api 电信客户流失预测案例 逻辑回归 逻辑回归简介 ​…

python爬虫 - 进阶正则表达式

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配中文 &#xff08;一&#xff09;匹配单个中文字符 &#xff08;二…

【网易云音乐】--源代码分享

最近写了一个网易云音乐的音乐实现部分&#xff0c;是通过JavaScript和jQuery实现的&#xff0c;具体效果大家可以参照下面的视频 源代码分享 - git地址: 网易云音乐源代码 下面将着重讲解一下音乐实现部分 视频有点模糊&#xff0c;不好意思&#xff0c;在b站上添加视频的时候…

【Oracle DB故障分享】分享一次由于SGA设置太小导致的DP备份失败

List item 今天给客户做Oracle例行数据库健康巡检&#xff0c;过程中检出一些备份异常&#xff0c;分享如下。 排查问题&#xff1a; 打开DP备份软件&#xff0c;随即弹出如下提示&#xff1a; 登录DP&#xff0c;查看备份情况&#xff1a;发现从10/6开始&#xff0c;DP备份…

ESP32—C3实现DS18B20(温度传感器)检测温度(Arduino IED )

1源代码&#xff08;DS18B20&#xff09; #include <OneWire.h> // 引入OneWire库&#xff0c;用于与单总线设备通信 #include <DallasTemperature.h> // 引入DallasTemperature库&#xff0c;用于读取DS18B20温度传感器数据// 定义连接到DS18B20数据引脚的GPIO编…

Vue入门-指令修饰符-@keyup.enter

指令修饰符&#xff1a; 通过"."指明一些指令后缀&#xff0c;不同后缀封装了不同的处理操作 ->简化代码 ①按键修饰符 keyup.enter ->键盘回车监听 ".enter"if(e.keyenter){} //".enter"用来简化代码 demo&#xff1a; <!DOCTYPE…

Ubuntu系统可以使用WIFI上网,而插网线有线网不能上网,网卡驱动未安装问题解决

文章目录 问题分析解决结果 问题 linux ubuntn系统下可以正常连WiFi上网&#xff0c;但是不能插网线上网。 分析 首先要排除是否为硬件问题&#xff0c;我在windows下是可以正常使用网线的&#xff0c;所以排除硬件的问题。 查看网卡是否被检测(wifi有说明网卡是有检测的) …

有了WPF后Winform还有活路吗?

近年来&#xff0c;随着技术的不断发展&#xff0c;Windows Presentation Foundation&#xff08;WPF&#xff09;和Windows Forms&#xff08;WinForms&#xff09;这两种技术在开发桌面应用程序方面一直备受关注。虽然WPF以其强大的功能和灵活性吸引了众多开发者&#xff0c;…