Codeforces Round #673 (Div. 2)A-E题解

管道铺设最优方案 N ( N>10 )个居民区之间需要铺设煤气管道。假设任意两个居民区之间都可以铺设煤气管道,但代价不同。事先将任意两个居民区之间铺设煤气管道的代价存入磁盘文件中。设计一个最佳方案使得这 N 个居民区之间铺设煤气管道所需代价最少 , 并希望以图形方式在屏幕上输出结果。 立即下载

Codeforces Round #673 (Div. 2)A-E题解

比赛链接:https://codeforces.com/contest/1417

A题
水,贪心

题意为给定一个长度为n的数列,并给定一个上限k,原数列中的每个数都在1到k之间,现在你每次操作都可以把当前数列中的某一个数字加到另一个数字上,但是不可以让数值超过k,现在询问最多可以操作多少次。

直接贪心选择值最小的那一个,把其他数字尽可能多得用这个最小值加就是了。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        int ans=0,tar=0;
        vector<int>num(n);
        for(int i=0;i<n;i++)
        {
            cin>>num[i];
            if(num[i]<num[tar]) tar=i;
        }
        for(int i=0;i<n;i++)
            if(i!=tar) ans+=(k-num[i])/num[tar];
        cout<<ans<<endl;
    }
} 

B题
贪心,构造

题意为给定一个长度为n的数列,并给定一个数值T,现在要求你把原数列分成两个数列,两个数列中在同一个数列里加起来等于T的数字下标对数最少。

贪心即可了,把小于T的一半的放进第一个数列,大于T的一半的放进第二个数列,刚好等于T一半的均匀分不到两个数列里即可。因为小于T的一半只能和大于T的一半加起来等于T,直接把他们分成两个部分即可,刚好等于一半的均匀分布这个结论自己稿纸上验算下就是了。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
        ll n,T;
        cin>>n>>T;
        bool flag=0;
        vector<bool>color(n);
        for(int i=0;i<n;i++)
        {
            ll x;
            cin>>x;
            if(x*2==T) {color[i]=flag;flag=!flag;}
            else if(x*2<T) color[i]=0;
            else color[i]=1;
        }
        for(int i=0;i<n;i++) cout<<color[i]<<' ';
        cout<<endl;
    }
}

C题
字符串,小结论,map简单运用

给定一个长度为n的数列,你需要输出对与取值1-n的k值,对与该数列中所有长度为k的连续子序列,共用的数字中最小的那一个。如果没有共有的数字,则输出-1。

如果直接从正面去考虑,会发现难以思考。我们可以从针对某一个具体的数值来看,如果这个数值作为某个长度k的最小公共值的话,长度k需要不小于这个数列中所有该值出现的位置中相邻位置的最大间距(注意在数列最左侧和最右侧要特殊判定)。利用这个结论我们可以借助map在一次for循环得到每个数值对应的最小k,记录后直接对kfor一遍1-n即为答案,输出最小k即可。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int32_t main()
{
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        map<int,pair<int,int>>M;//M[i]=pair{j,k},代表值为i的数字最后出现在下标j的位置,值为i的数字之间的最大间隔为k
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            if(M.find(x)==M.end()) M[x]=make_pair(i,i);//数列左侧特判
            else
            {
                M[x].second=max(M[x].second,i-M[x].first);
                M[x].first=i;
            }
        }
        vector<int>ans(n+1,INF);
        for(auto &x:M)
        {
            x.second.second=max(x.second.second,n+1-x.second.first);//特判数列右侧
            ans[x.second.second]=min(ans[x.second.second],x.first);
        }
        int now=INF;
        for(int i=1;i<=n;i++)
        {
            now=min(now,ans[i]);
            if(now==INF) cout<<-1<<' ';
            else cout<<now<<' ';
        }
        cout<<endl;
    }
}

D题
构造,思维

题意为给定一个长度为n的数列,其中的每个数的数值都为1到1e5之间的正整数,现在你需要在最多3n次操作内,使得这个数列中的每一个数的值相等。
每次操作你可以选择两个下标i和j,并且选定一个0到1e9之间的自然数x,对ai减去i ×\times× x,对aj加上i ×\times× x。

首先注意到整个数列的和在操作过程中是没被改变过的,因此首先整个数列的和需要能被数列长度n整数才可能构造。之后我们注意到这里操作的特殊性在于我们对两个下标增减的数值是需要乘以下标i的,那么很容易想到的下标1的数如果足够大,就可以在一次操作满足我们任意一个位置的构造,那么能否先通过某种方式把整个数列所有的数值聚集到a1上,再for一次n分配的所有位置上呢。我们注意到如果我们想把aj位置上的所有数值都移动到a1上,aj的值需要整除j才行,那么如果aj的值无法整除j,我们需要从别的地方补数值到aj上去。
很容易的我们也会想到利用a1补到aj上使得aj整除j,然后就会发现…直接for一遍2到n必定可以完成这样的清零a2到an的操作,因为原数列中每个数都是正整数,也就是说前n个数的和至少为n,也就是说必然能使得aj的值变为能被j整除。
所以我们第一遍for下标2到n,每次循环两轮操作,第一轮操作把a1的值补到aj上使得aj能被j整除,第二轮操作把aj的所有值移动到a1上。
这样一轮操作消耗了2n-2次,把整个数列所有值都移动到了a1上,之后再for一遍2到n的下标,从a1直接把值移动过来构造即可。总共消耗3n-3次操作,必定完成构造。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const ll maxn=1e4+7;

ll num[maxn];
ll n,sum;

int32_t main()
{
    IOS;
    int t;
    cin>>t;
    while(t--)
    {
        sum=0;
        cin>>n;
        for(ll i=1;i<=n;i++) {cin>>num[i];sum+=num[i];}
        if(sum%n) cout<<-1<<endl;
        else
        {
            sum/=n;
            cout<<3*(n-1)<<endl;
            for(ll i=2;i<=n;i++)//第一遍for把除了num[1]外的所有值清零,移动到num[1]上
            {
                ll temp=i-num[i]%i;
                if(temp==i) temp=0;
                cout<<1<<' '<<i<<' '<<temp<<endl;
                num[1]-=temp;
                num[i]+=temp;
                cout<<i<<' '<<1<<' '<<num[i]/i<<endl;
                num[1]+=num[i];
            }
            for(ll i=2;i<=n;i++) cout<<1<<' '<<i<<' '<<sum<<endl;//第二遍for直接利用num[1]构造
        }
    }
}

E题
位运算,dfs分治,结论

题意为给定一个长度为n的只包含自然数的数列,你需要找到一个合适的值out,使得对原数列中每个数值都异或x后得到一个新数列,这个新数列中逆序对的数量num最小,输出这个最小的num和对应的out值。

这里需要认识到,假设只有0和1的数列,我们可以通过一次for循环的过程中,记录0和1出现了几次,以0和以1为结尾构成逆序对的数量,根据两个值的大小差别决定我们是用0还是用1去异或他们。
由此之后,
我们从高位到低位看,根据取值的不同,数列会被分为2的对应深度次方的几个集合,对于不同的集合来说,他们之间的逆序对数量是已经在前面的层数过程中根据上面一段的计算过程可以求得,之后各个集合之间再也不会产生影响,因为后续只对更低位产生影响,不会对当前集合之间的关系产生影响。
推到此处之后直接写一个dfs分治即可。

#include<bits/stdc++.h>
#define ll long long
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int n;
ll ans=0,out=0;//ans为最终的数列中逆序对的数量,out为对原数列中每个值进行异或的值

void dfs(vector<vector<ll>>now,int deep)//二维数组now记录数列在当前层数被分割成了几个部分,deep为当前算的是二进制第几位
{
    ll temp=1ll<<deep;
    ll cas0,cas1,sum0=0,sum1=0;//sum0和sum1分别记录当前二进制deep位上,以该位为0的值作为逆序对的右侧(也就是out在此位取0)的逆序对数量
    //和以该位为1的值作为逆序对的右侧(也就是out在此位取1,使得该位的所有数0和1转化)的逆序对数量
    vector<vector<ll>>next;//下一次dfs的二维数组
    vector<ll>next0,next1;//当前分割部分的vector中,二进制deep位为0和1的数字分别放入两个vector
    for(int i=0;i<now.size();i++)
    {
        cas0=cas1=0;
        for(int j=0;j<now[i].size();j++)
        {
            if(now[i][j]&temp) {sum1+=cas0;cas1++;next1.push_back(now[i][j]);}
            else {sum0+=cas1;cas0++;next0.push_back(now[i][j]);}
        }
        if(next0.size()) {next.push_back(next0);next0.clear();}//避免不需要的递归和空间浪费,如果next0和next1不为0才压入下次dfs的数组里
        if(next1.size()) {next.push_back(next1);next1.clear();}
    }
    if(sum0>sum1) {ans+=sum1;out+=temp;}//如果以该位为0的值作为逆序对右侧的逆序对数量大于以该位为1的值作为逆序对的右侧,代表out需要在该位取1
    else ans+=sum0;
    if(deep==0) return;
    dfs(next,deep-1);
}

int32_t main()
{
    IOS;
    cin>>n;
    vector<vector<ll>>num(1);
    num[0].resize(n);
    for(auto &x:num[0]) cin>>x;
    dfs(num,30);//dfs30层即可,1e9的最高位也不过2的30次
    cout<<ans<<' '<<out<<endl;
}
油井问题(算法设计与分析作业) 主油管道为东西向,确定主油管道的南北位置,使南北向油井喷油管道和最小。要求线性时间完成。 1<= 油井数量 <=2 000 000 输入要求: 输入有油井数量行,第 K 行为第 K 油井的坐标 X ,Y 。其中, 0<=X<2^31,0<=Y<2^31 。 输出要求: 输出有一行, N 为主管道最优位置的最小值 注意:用快排做的不给分!! 友情提示:可以采用while(scanf("%d,%d",&x,&y) != EOF)的数据读入方式。 测试输入关于“测试输入”的帮助 期待的输出关于“期待的输出”的帮助 时间限制关于“时间限制”的帮助 内存限制关于“内存限制”的帮助 额外进程关于“{$a} 个额外进程”的帮助 测试用例 1 以文本方式显示 41,969978↵ 26500,413356↵ 11478,550396↵ 24464,567225↵ 23281,613747↵ 491,766290↵ 4827,77476↵ 14604,597006↵ 292,706822↵ 18716,289610↵ 5447,914746↵ 以文本方式显示 597006↵ 1秒 64M 0 立即下载

相关推荐

计算机算法设计与分析(油井铺设问题)

此程序采用C++编写,程序中有一份txt程序说明,该程序王晓东编写计算机算法设计与分析第2章课后题

铺设油井管道

铺设油井管道问题描述: 某石油公司有n口油井,为方便输送石油,计划修建输油管道。根据设计要求,水平方向有一条主管道,每口油井修一条垂直方向的支线管道通向主管道。请设计一种算法确定主管道的位置,使得所有油井到主管道之间的支线管道长度的总和最小。提示:复杂度为O(n)才能通过所有测试用例。 输入格式: 每个输入文件为一个测试用例,每个文件的第一行给出一个正整数n(1≤n≤1000000),表示油井数量,从第二行起的n行数据,表示每口油井的位置,每行包含以空格分隔的两个整数,分别表示每口油井的横坐标x(−1000

qq_49222080的博客 2882

图着色问题

这是一个关于图作色算法的C++源代码,代码中有相应的注释,适合初学者,包含算法和测试两部分,测试时主函数部分代码。

铺设油井管道问题(分治法实现)

铺设油井管道: 某石油公司有n口油井,为方便输送石油,计划修建输油管道。根据设计要求,水平方向有一条主管道,每口油井修一条垂直方向的支线管道通向主管道。请设计一种算法确定主管道的位置,使得所有油井到主管道之间的支线管道长度的总和最小。

qq_74297134的博客 1602

Java Web 图书管理系统的制作指南

实现对图书信息的增删改查(CRUD)操作。支持用户登录与权限管理。图书借阅与归还功能。系统管理员可以管理用户信息和图书库存。

Xiaoxin的博客 1629

微信小店推客分销系统源码获取与自研开发全攻略(2025年最新版)

源码选择建议快速试错:选用开源项目(如启航系统),3天可上线基础功能长期布局:购买商业源码授权,重点定制分佣规则与UI交互完全自研:适合年GMV过亿的大型企业,需前置投入风控与合规设计行动清单注册微信开放平台账号,完成视频号机构认证下载开源项目代码,部署本地测试环境联系三家源码供应商,获取合规性审计报告设计三级分佣比例表,通过法律顾问合规审查通过以上路径,可高效构建合规、稳定、高转化的微信小店推客分销系统,抢占2025年视频号电商红利。

2401_85184777的博客 1283

输油管道问题

描述 某石油公司计划建造一条由东向西的主输油管道。该管道要穿过一个有n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。如果给定n口油井的位置,即它们的x 坐标(东西向)和y 坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置?证明可在线性时间内确定主管道的最优位置。 编程任务: 给定n 口油井的位置,编程计算各油

吃葡萄不吐葡萄皮 2517

FFmpeg实战:5分钟搞定m3u8视频下载与ts文件合并(附完整命令)

本文详细介绍了如何使用FFmpeg快速下载m3u8视频并合并ts文件为mp4格式。通过简洁的命令行操作,读者可以轻松完成视频处理任务,包括环境准备、链接获取、下载合并及性能优化等实用技巧,特别适合需要高效处理流媒体内容的用户。

weixin_30836759的博客 221

c++基础入门:输油管道问题

如果给定n 口油井的位置,及它们的x 坐标(东西向和y 坐标(南北向),应如何确定主管道的最优位置,即使各油井到主管道之间的输油管道长度总和最小的位置?证明可规定时间内确定主管道的最优位置。该管道要穿过一个有n口油井的油田。从每口油井都要有一条输油管道沿最短路径(或南或北)与主管道相连。接下来n 行是油井的位置,每行 22 个整数x 和y。只有一行,表示油井到主管道之间的输油管道最小长度总和。某石油公司计划建造一条由东向西的主要输油管道。

m0_72614289的博客 624

工业自动化实战:用LabVIEW的DSC模块实现MODBUS-TCP设备控制

本文详细介绍了如何利用LabVIEW的DSC模块实现工业自动化中的MODBUS-TCP设备控制。通过环境准备、核心功能解析、状态机实现及典型工业场景实战,帮助工程师快速掌握稳定可靠的通讯技术,提升工业自动化系统的运行效率。

salt9的博客 1057

相控阵雷达“相控”原理---多张动画示意图完美解释

很容易就能发现,相控阵雷达的天线由无数个小单元天线组成,这些小单元天线叫做“阵元”,对于有源相控阵雷达来说,每一个阵元都是独立控制的,它们既能独立发射雷达波,也能接收雷达波的回波信号。相控阵雷达可以在1秒内关机,1秒内开机,好处是,当军舰遇到依靠雷达信号进行引导的“反雷达导弹”时,可以迅速地把朝向来袭导弹方向的雷达关机,同时,其他方向的雷达保持开启。在过去,军舰上安装有不同种类的雷达,体积庞大、重不说,另一个麻烦是干扰,常常是,一种雷达工作时,另一种雷达就会受到干扰,严重的甚至不能同时工作。

muyangjun的专栏 1万+

L2-023 图着色问题

图着色问题是一个著名的NP完全问题。给定无向图G=(V,E),问可否用K种颜色为V中的每一个顶点分配一种颜色,使得不会有两个相邻顶点具有同一种颜色? 但本题并不是要你解决这个着色问题,而是对给定的一种颜色分配,请你判断这是否是图着色问题的一个解。 输入格式: 输入在第一行给出3个整数V(0<V≤500)、E(≥0)和K(0<K≤V),分别是无向图的顶点数、边数、以及颜色数。顶点和...

沐妖的博客 495

PHP项目实战:易宝支付SDK对接全流程(含回调处理与常见问题排查)

本文详细介绍了PHP项目中易宝支付SDK的对接全流程,包括环境准备、SDK配置、支付请求构建与发起、回调处理实战以及常见问题排查。特别针对回调处理环节的常见问题提供了解决方案,帮助开发者快速完成支付对接并优化性能。

weixin_29007809的博客 388

Codeforces Round #673 (Div. 2)

Codeforces Round #673 (Div. 2) 传送门 A. Copy-paste 题解 贪心,最小的一个个往后加。 代码 #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #define ll long long using namespace std; int a[1005]; int m

weixin_44049050的博客 211

⭐️【2024年新版教程】vmware tools安装步骤(Windows、Linux、MacOS版本)

VMware Tools是VMware提供的一套实用工具,它可以增强虚拟机与宿主机之间的交互性能,如改进显示性能、优化鼠标和键盘性能、提供时间同步功能等。无论是在Windows、Linux还是MacOS虚拟机上,安装VMware Tools都可以提高虚拟机的使用体验。以上就是在不同操作系统上安装VMware Tools的步骤,希望对您有所帮助。

Python老吕的博客 6万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Codeforces Round #673 (Div. 2) D 和 E

D 题意 给定一个长度为n为的数组,并且a[i] >= 1 每次可以选择两个数一个为 i,j 并选 则一个x给 a[i] -= x * i, a[j] += x * i 最终是所有的元素大小都相等,并且 每次操作完之后所有元素的大小都是非负的 题解 我们可以发现每次都是给整个数组加上一个数减去一个数,数组的总大小不变 所以只有当所有元素的和是n的倍数才能满足条件,至于操作我们可以客观的想 因为只有第一个数是我们可控(即他是所有数的约数),所有我们就可以先把所 有的数都变为0,然后在变为 sum /

qq_45074215的博客 253

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Codeforces Round #673 (Div. 2) Sep/27/2020 23:05UTC+8

Codeforces Round #673 Div. 2 Sep/27/2020 23:05UTC+8C. k-Amazing NumbersD. Make Them EqualE. XOR Inverse 比赛链接:https://codeforces.com/contest/1417 比赛记录:https://blog.csdn.net/cheng__yu_/article/details/105395197 C. k-Amazing Numbers 题意:给定一个长度为 nnn 的序列,问在所有 kk

qq_17080419的博客 282

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Codeforces Round #673 (Div. 1)

A.k-Amazing Numbers http://codeforces.com/contest/1416/problem/A 给定一个长为nnn的数组a[],定义“k-Amazing Number”是最小的、满足在数组a[]中的任意连续k个数字中出现至少一次的数字。 现在给定数组a[],依次求"1…n-Amazing Number",不存在则输出-1。 (多组数据) #include<stdio.h> #include<map> #include<queue> #in

asdkjc的博客 284

Codeforces Round #690 (Div. 3)

文章目录Codeforces Round #690 (Div. 3)A.Close TuplesB.Close TuplesC.Close TuplesD.Close TuplesE.Close TuplesF.The Treasure of The Segments Codeforces Round #690 (Div. 3) 比赛的时候f想到思路,写了一半比赛就结束了,难受 A.Close Tuples 题意: 题解: 代码: /* 6 7 3 4 5 2 9 1 1 4 9 2 7 1 11 8 4

m0_49959202的博客 217

Codeforces Round #673 (Div. 2) A-C(思维,思维,思维+贪心+整体观)

Codeforces Round #673 (Div. 2) A. Copy-paste 题意: 你有 n个 堆糖果每堆糖果都有一定的数量 ,你会魔法 可以将任意一堆的糖果复制到 另一堆里(其中1.不可以是复制自己到自己2.每堆糖果的数量不能超过k个)求最多可以复制的次数 问题分析: 肯定就是 找到最小的呢一堆,然后将这一堆一直复制到其他的糖果堆了直到不超过k的最大值 我是 sort了一遍 不然就需要 记录最小值的位置,因为可以最小值柯南不唯一 AC代码: #include<map> #incl

MaxVen 195

Codeforces Round #673 (Div. 2) E. XOR Inverse (字典树 + 分治)

链接 E. XOR Inverse 题意: 给一个数组 ,需要找到一个 X ,使数组中每个数 异或 X 后 ,数组中的逆序对数最少 ,如果有多个 X 找最小的那个,求 X和逆序对数。 思路: 比较两个数的大小 ,其实就是比较两个数的二进制位第一个大小不同的位置的大小,因为字典树可以保存相同的前缀,所以我们先用字典树把这些数字存起来,用 vector 存一下当前前缀相同相同的每个数的位置。 考虑每个二进制位 , 因为我们已经记录了这一位为 0 和 1 的数的位置,所以可以直接求出逆序对数 , 这样我们就

hddddh的博客 514

Codeforces Round #670 (Div. 2)

Codeforces Round #670 (Div. 2) 传送门 A. Subset Mex Description Given a set of integers (it can contain equal elements). You have to split it into two subsets A and B (both of them can contain equal elements or be empty). You have to maximize the value of .

Silence的博客 240

Codeforces Round #673 (Div. 2) Solved: 4 out of 6

Codeforces Round #673 (Div. 2) 题目 A B C D E F solved ✔ ✔ ⚪ ⚪ - - ✔:比赛时通过;⚪:比赛时尝试了但未通过 A. Copy-paste 题意: 给定n个数,从其中选择一个数作为底数,然后可以给其他的数作加法(加上这个底数,每加一次算作一次操作)。要求做加法之后所有的数都必须≤K。问最多可以执行几次操作。 题解: 找到最小数,然后做加减乘除就可。 #include<bits/stdc++.h> using nam

lllllan 172
上一篇: Codeforces Round #672 (Div. 2)A-D题解
下一篇: Codeforces Round #674 (Div. 3)A-F题解
StandNotAlone
博客等级 码龄7年 338粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值