当前位置: 首页 > news >正文

AtCoder Beginner Contest 396(ABCDEF)

目录

A - Triple Four

翻译:

思路:

实现:

B - Card Pile

翻译:

思路:

实现:

C - Buy Balls

翻译:

思路:

实现:

D - Minimum XOR Path

翻译:

思路:

实现:

E - Min of Restricted Sum

翻译:

思路:

实现:

F - Rotated Inversions

翻译:

思路:

实现:


A - Triple Four

翻译:

        你被给予一个长度为N的整数序列A=(A_1,A_2,...,A_N)

        确定A中是否存在一个地方连续出现三次或更多相同的元素。

        更正式地,决定是否存在一个整数 i (1<=i<=N-2)如此A_i=A_{i+1}=A_{i+2}

思路:

        遍历A,判断A_i=A_{i+1}=A_{i+2}是否存在。

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MX = 1e5+10;

void solve(){
    int n;cin>>n;
    vector<int> a(n);
    for (int &i:a)cin>>i;
    for (int i=0;i<n-2;i++){
        if (a[i]==a[i+1]&&a[i+1]==a[i+2]){
            cout<<"Yes"<<endl;
            return;
        }
    }
    cout<<"No"<<endl;
}

int main(){
    // 关闭输入输出流同步
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 不使用科学计数法
    // cout<<fixed;
    // 中间填保留几位小数,不填默认
    // cout.precision();
    solve();
}



B - Card Pile

翻译:

       有一叠 100 张卡片,每张都标有整数 0。

       处理 Q 个查询。每个查询都属于以下类型之一:

  • 类型 1:将一张标有整数 x 的卡片放在堆栈顶端。
  • 类型 2:取出堆栈顶端的卡片,并输出写在该卡片上的整数。在此问题的限制条件下,牌堆中总是至少有一张牌。
     

思路:

        这是一种数据结构先进先出(栈)。

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MX = 1e5+10;

void solve(){
    int n;cin>>n;
    stack<int> nums;
    for (int i=0;i<100;i++) nums.push(0);
    int f,id;
    while (n--){
        cin>>f;
        if (f==1){
            cin>>id;
            nums.push(id);
        }else{
            cout<<nums.top()<<"\n";
            nums.pop();
        }
    }
}

int main(){
    // 关闭输入输出流同步
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 不使用科学计数法
    // cout<<fixed;
    // 中间填保留几位小数,不填默认
    // cout.precision();
    solve();
}



C - Buy Balls

翻译:

        有 N 个黑球和 M 个白球。

        每个球有一个值。第 i 个黑球(1≤i≤N)的值为 B_i,第 j 个白球(1≤j≤M)的值为 W_j。.

        选择 0 个或更多的球,使得所选黑球的个数至少等于所选白球的个数。在所有这些选择中,求所选球的最大可能数值之和。

思路:

        题目要求黑球数量>=白球数量。贪心要选就选大的,要选就选正的。

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MX = 1e5+10;

void solve(){
    ll cnt_b,cnt_w;
    cin>>cnt_b>>cnt_w;
    vector<ll> W(cnt_w),B(cnt_b);
    for (ll &i:B) cin>>i;
    for (ll &i:W) cin>>i;
    sort(W.begin(),W.end(),greater<int>());
    sort(B.begin(),B.end(),greater<int>());
    ll ans = 0;
    ll j = 0,now_W=0,now_B = 0;
    for (ll i=0;i<cnt_b;i++){
        now_B += B[i];
        for (;j<=i && W[j]>0 && j<cnt_w;j++) now_W+=W[j];
        ans = max(ans,now_B+now_W);
    }
    cout<<ans<<endl;
}

int main(){
    // 关闭输入输出流同步
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 不使用科学计数法
    // cout<<fixed;
    // 中间填保留几位小数,不填默认
    // cout.precision();
    solve();
}

 

D - Minimum XOR Path

翻译:

        给你一个简单相连的无向图,图中有 N 个顶点(编号为 1 到 N)和 M 条边(编号为 1 到 M)。边 i 连接顶点 u_iv_i,其标签为 w_i .

        在所有简单路径(不多次通过同一顶点的路径)中,从顶点 1 到顶点 N 的所有简单路径(不多次经过同一顶点的路径)中,求路径上边的标签的最小XOR。

思路:

        N的最大为10,那么暴力考虑事件复杂度为9!=362880<1e7。当算出来的时间复杂度<=1e7时一般这个算法就是可行的。所以直接深搜每条1到n的路径。(dfs)

实现:

#include<bits/stdc++.h>
using namespace std;
#define int  long long
const int MX = 11;
int n,m;
int ans = LLONG_MAX;
vector<vector<int>> graph(MX,vector<int>(MX,-1));
vector<int> vis(MX,0);
void dfs(int index,int val){
    if (index==n){
        ans = min(ans,val);
        return;
    }
    for (int i=1;i<=n;i++){
        if (graph[index][i]!=-1 && !vis[i]){
            vis[i] = 1;
            dfs(i,val^graph[index][i]);
            vis[i] = 0;
        }
    }
}
void solve(){
    cin>>n>>m;
    for (int u,v,w,i=1;i<=m;i++){
        cin>>u>>v>>w;
        graph[u][v] = graph[v][u] = w;
    }
    vis[1] = 1;
    dfs(1,0);
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    solve();
}

E - Min of Restricted Sum

翻译:

        给你整数 N,M 和三个长度为 M 的整数序列:X=(X_1,X_2,...,X_M),Y=(Y_1,Y_2,...,Y_M),Z=(Z_1,Z_2,...,Z_M)。保证 X 和 Y 的所有元素都在 1 到 N 之间。

        我们称长度为 N 的非负整数序列 A=(A_1,A_2,...,A_N) 为良好序列,当且仅当它满足以下条件时:

  •         对于 1≤i≤M 的每一个整数 i,A_{X_i}A_{Y_i}的 XOR 为 Z_i .

        判断一个好的序列 A=(A_1,A_2,...,A_N)存在,并且如果存在,找出一个和最小的好序列。\sum^{N}_{i=1}A_i

思路:

        异或有一个性质A^B=C,A^C=B,B^C=A。例如a->b异或得到x那么a^x=b,b^x=a。如何判断好序列存在呢?根据条件建立一个无向图,如果图中相连部分有不满足条件(如点b到点c得到10,而点a到点c得到的不是10)的输出-1。

        那么如何得到和最小的好序列呢?想到异或是针对每个数的二进制数位的,也就是说每个数与它相连的数的相同数位变化是同时的,那么要让和最小就要让同一个联通块的每个二进制数位的0数量大于等于1的数量。(bfs,位运算)

实现:

#include<bits/stdc++.h>
using namespace std;
void solve(){
    int n,m;
    cin>>n>>m;
    // index val
    vector<vector<pair<int,int>>> graph(n+1);
    for (int i=1,u,v,w;i<=m;i++){
        cin>>u>>v>>w;
        graph[u].push_back({v,w});
        graph[v].push_back({u,w});
    }
    // 记录答案
    vector<int> ans(n+1,-1);
    for (int i=1;i<=n;i++){
        if (ans[i]!=-1) continue;
        ans[i] = 0;
        vector<int> groups={i};
        // bfs:搜索与i有关的连通块
        for (int j=0;j<groups.size();j++){
            int val = ans[groups[j]];
            for (auto& [to,now_val]:graph[groups[j]]){
                if (ans[to]==-1){
                    groups.push_back(to);
                    ans[to] = now_val^val;
                }else if (ans[to]!=(now_val^val)){
                    cout<<-1<<endl;
                    return;
                }
            }
        }
        // 遍历位数
        for (int j=0;j<=30;j++){
            int cnt1 = 0;
            // 第j位中有多少1
            for (auto& num:groups){
                if (ans[num]&(1<<j)){
                    cnt1++;
                }
            }
            // j位中1的数量大于0的数量
            if (2*cnt1>groups.size()){
                // 将j位中1,0互换
                for (auto &num:groups){
                    ans[num]^=(1<<j);
                }
            }
        }
    }
    for (int i=1;i<=n;i++){
        if (i!=1) cout<<" ";
        cout<<ans[i];
    }
}
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    solve();
}

F - Rotated Inversions

翻译:

        给你整数 N,M 和长度为 N 的非负整数序列 A=(A_1,A_2,...,A_n)

        对于 k=0,1,...,M-1,求解以下问题:

        定义一个整数序列 BB=(B_{1},B_{2},...,B_N),使得 B_{i}A_{i}=k 除以 M 的余数。找到B的逆序对数量。

思路:

        对于k变为k+1时,哪些值是对逆序对数量有影响的?k+1时会到m变为0的值。那么在k=0的基础上,当k=i时要找值为m-i的下标的数组change。change中第 i 个值,在这 i 个前面的值除去change中的都为逆序对 : chage[i] - 1 -i 。i 后面的值除去change中的都不为逆序对:n-change[i]-(change.size()-(i+1))。

        那么原数组怎么求逆序对呢?使用权值线段树求逆序对,对于每个插入的数求出大于该数的数量。(zkw线段树)

实现:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MX = 2e5;
// 权值线段树
ll tree[MX<<2];
ll tree_m;
void add(ll position){
    for (position+=tree_m;position>0;position>>=1){
        tree[position]++;
    }
}
ll find(ll l,ll r){
    ll res = 0;
    for (l+=tree_m,r+=tree_m;l<=r;l>>=1,r>>=1){
        if (l%2==1) res+=tree[l++];
        if (r%2==0) res+=tree[r--];
    }
    return res;
}
void solve(){
    ll n,m;
    cin>>n>>m;
    tree_m = 1;
    while (tree_m<m) tree_m<<=1;
    ll cnts = 0;
    vector<ll> a(n+1);
    vector<vector<ll>> change(m);
    for (ll i=1;i<=n;i++) {
        cin>>a[i];
        change[a[i]].push_back(i);
        // 求version number
        add(a[i]);
        cnts+=find(a[i]+1,m);
    }
    cout<<cnts<<"\n";
    // 当k为i是要关心m-i
    for (ll i=m-1;i>=1;i--){
        ll now_cnt = 0;
        for (ll j=0;j<change[i].size();j++){
            now_cnt += change[i][j]-1-j;
            now_cnt -= n-change[i][j]-(change[i].size()-(j+1));
        }
        cnts+=now_cnt;
        cout<<cnts<<"\n";
    }
}

signed main(){
    // 关闭输入输出流同步
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    // 不使用科学计数法
    // cout<<fixed;
    // 中间填保留几位小数,不填默认
    // cout.precision();
    solve();
}

  有建议可以评论,我会积极改进qwq。

相关文章:

  • 【LLM】大模型推理、微调显卡挑选一览表
  • 【论文解读】《LIMO: Less is More for Reasoning》
  • PHP的Workerman 和 Java 常驻内存的相似性
  • Java【网络原理】(3)网络编程续
  • 如何避免项目后期盲目加人赶工
  • 机试准备第13天
  • 知识蒸馏综述Knowledge Distillation: A Survey解读
  • 国产算力助力工业智能新范式
  • PyTorch 学习路线
  • 探秘 Netty 通信中的 SslHandler 类:保障网络通信安全的基石
  • 【MySQL】发展起源与核心架构组件详细介绍
  • STL之list的使用(超详解)
  • 【时间序列】Patch:到底是什么?
  • 【极光 Orbit•STC8A-8H】03. 小刀初试:点亮你的LED灯
  • 数字信号处理之信号功率谱计算welch方法(分段加窗平均周期图)、Bartlett方法(周期图)(Python)
  • 以网络形式启动Linux系统后,通过挂载(mount)的方式,将eMMC存储器中旧的根文件系统所在逻辑2分区格式化,并解压新的根文件系统到逻辑2分区
  • 【Linux文件IO】标准IO详情(1)
  • kubernetes——part3-5 核心概念 Service
  • 知识图谱相关的Terse RDF Triple Language 文件格式介绍
  • 如何提高域名解析速度?
  • 基于b s结构做的网站/许昌网络推广外包
  • 网站建设与维护网课/网络公司起名
  • 动态公司网站设计/昆明seo优化
  • 如何做影视网站/网络小说网站三巨头
  • 城乡建设部网站混凝土7天强度/seo对网络推广的作用是
  • 凡科的模板做网站/大数据精准营销获客