Codeforces Round 954 (Div. 3) (A~F)(不会数学)

A - X Axis 

        

暴力枚举一下所有可能

void solve() 
{
	int a , b , c;
	cin >> a >> b >> c;
	int ans = 100;
	for(int i = 0 ; i <= 10 ; i ++){
		ans = min(ans , abs(i - a) + abs(i - b) + abs(i - c));
	}	
	cout << ans << endl;
}    

B - Matrix Stabilization 

        

可以观察到:若一个数比周围四个数都大,那么最终会变成四个数当中最大的哪一个。

        

void solve() 
{
	int n , m;
	cin >> n >> m;
	int mp[n][m];
	for(int i = 0 ; i < n ; i ++){
		for(int j = 0 ; j < m ; j ++){
			cin >> mp[i][j];
		}
	}	
	for(int i = 0 ; i < n ; i ++){
		for(int j = 0 ; j < m ; j ++){
			int ma = -1;
			if(i > 0){
				ma = max(ma , mp[i - 1][j]);
			}
			if(i + 1 < n){
				ma = max(ma ,  mp[i + 1][j]);
			}
			if(j > 0){
				ma = max(ma , mp[i][j - 1]);
			}
			if(j + 1 < m){
				ma = max(ma , mp[i][j + 1]);
			}
			cout << min(mp[i][j] , ma) << " ";
		}
		cout << endl;
	}
}   

C - Update Queries 

        

对字符串c以及ind数组进行排序,通过贪心可以知道,我们需要按照索引从小到大的修改字符串,同时一个位置只会有一个字母与之对应,因此只需要同时按照字符串c从小到大修改即可。

        

void solve() 
{
	int n , m;
	cin >> n >> m;
	string s;
	cin >> s;	
	int a[m];
	map<int,int>mp;
	for(int i = 0 ; i < m ; i ++){
		cin >> a[i];
		mp[a[i]]++;
	}
	char c[m];
	string str;
	cin >> str;
	for(int i = 0 ; i < m ; i ++){
		c[i] = str[i];
	}
	sort(c , c + m);
	int id = 0;
	for(auto it : mp){
		int x = it.first;
		x--;
		s[x] = c[id++];
	}
	for(int i = 0 ; i < n ; i ++){
		cout << s[i];
	}
	cout << endl;
}   

D - Mathematical 问题 

        

      归纳题,观察后可以发现:一定有一个两位数,因此我们可以枚举这个两位数,然后取最小值。

        接下来考虑如何取最小值:若存在数字0,那么可以通过都用乘法来将最终结果变成0,此外,若存在数字1,可以通过乘法将1消掉。除此之外的数,都是加法更加小。按照此策略来模拟即可。

        

void solve() 
{
	int n;
	cin >> n;
	string s;
	cin >> s;
	int mask[n];
	for(int i = 0 ; i < n ; i ++){
		mask[i] = s[i] - '0';
	}	
	int ans = 101010;
	for(int i = 1 ; i < n ; i ++){
		vector<int>tmp;
		int tot = 0;
		for(int j = 0 ; j < n ; j ++){
			if(j == i - 1){
				int x = mask[j] * 10 + mask[j + 1];
				tmp.pb(x);
				j++;
			}
			else{
				tmp.pb(mask[j]);
			}
		}
		for(auto it : tmp){
			if(it == 0){
				cout << 0 << endl;
				return;
			}
			if(it == 1){
				continue;
			}
			else{
				tot += it;
			}
		}
		if(tot == 0) tot++;
		ans = min(ans , tot);
	}
	cout << ans << endl;
}  

E - Beautiful Array 

        

        思路:我们对所有模k情况下相同的数放到一组,组内的任意两个数都可以通过操作变成相同的数。然后考虑一个组内怎么样才能使得答案最小,显然将相近的两个数放到两边可以将答案变小。因此只需要排序,然后对相邻的两个数两两配对即可。由于需要两两配对,因此若一个组内的数的个数为奇数,除非将一个数放在正中间,否则一定无法满足题意。

        若n为奇数,那么需要有一个数放在正中间,也就是需要有一个组内的数的个数为奇数。接下来考虑怎么计算将谁放在中间最合适。假设组内数的个数为n,那么需要找出k = n/2组数来进行配对,考虑将某个位置上的数放到中间后的答案是怎样的:从开头两两配对所组成的x组 + 从结尾两两配对所组成的y = k - x(0\leq x \leq k)。因此可以通过一个前缀数组跟一个后缀数组来记录这些值,然后遍历x来找到最小值。

        

void solve() 
{
	int n , k;
	cin >> n >> k;
	vector<int>idx[n];
	map<int,int>mp;
	int id = 0;
	set<int>st;		
	for(int i = 0 ; i < n ; i ++){
		cin >> a[i];
		int res = a[i] % k;
		if(st.count(res)){
			int idk = mp[res];
			idx[idk].pb(a[i] / k);
		}
		else{
			st.insert(res);
			mp[res] = id++;
			idx[mp[res]].pb(a[i] / k);
		}
	}
	int ans = 0;
	int f = 0;
	if(n & 1){
		f++;
	}
	for(int i = 0 ; i < id ; i ++){
		sort(idx[i].begin() , idx[i].end());
		if(idx[i].size() % 2 == 0){
			for(int j = 0 ; j < idx[i].size() ; j += 2){
				ans += idx[i][j + 1] - idx[i][j];
			}
		}
		else{
			if(f){
				int k = idx[i].size() / 2;
				vector<int>pre(k + 5  , 0);//总共k个值
				int id = 1;
				for(int j = 0 ; j + 1 < idx[i].size() ; j += 2){
					pre[j / 2 + 1] = pre[j / 2] + idx[i][j + 1] - idx[i][j];
				}				
				vector<int>suf(k + 5 , 0);
				for(int j = idx[i].size() - 1 ; j >= 1 ; j -= 2){
					suf[j / 2 - 1] = suf[j / 2 ] + idx[i][j] - idx[i][j - 1];
				}
				int ma = 1e18;
				for(int j = 0 ; j <= k ; j ++){
					ma = min(ma , pre[j] + suf[j]);
				}
				ans += ma;
				f--;
			}
			else{
				f = -1;
				break;
			}
		}
	}
	if(!f){
		cout << ans << endl;
	}
	else{
		cout << -1 << endl;
	}
}   

 F - Non-academic 问题

        

        可以发现:若存在一个多元环(环上的点大于2),那么无法通过删除一条边来改变他们的连通情况。因此,对于那些多元环而言,我们可以将其缩成一个点。最终:我们通过缩点可以得到一个没有环的连通图,也就是树。接下来只需要通过枚举树上的每条边,将其变成两棵树,然后求出答案的最小值即可。

        用无向图的tarjan可以将这些多元环缩成一个点,然后再用树的算法来统计子树的大小跟答案即可。(无向图的tarjan跟有向图的tarjan很像,只需要一条边不连续走两次即可)

        

        

// Problem: F. Non-academic Problem
// Contest: Codeforces - Codeforces Round 954 (Div. 3)
// URL: https://codeforces.com/contest/1986/problem/F
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define x first
#define y second 
#define endl '\n'
#define int long long
const LL maxn = 4e05+7;
const LL N = 5e05+10;
const LL mod = 1e09+7;
const int inf = 0x3f3f3f3f;
const LL llinf = 5e18;
typedef pair<int,int>pl;
priority_queue<LL , vector<LL>, greater<LL> >mi;//小根堆
priority_queue<LL> ma;//大根堆
LL gcd(LL a, LL b){
	return b > 0 ? gcd(b , a % b) : a;
}

LL lcm(LL a , LL b){
	return a / gcd(a , b) * b;
}
int n , m;
vector<int>a(N , 0);
void init(int n){
	for(int i = 0 ; i <= n ; i ++){
		a[i] = 0;
	}
}
struct SCC {
    int n;
    std::vector<std::vector<int>> adj;//邻边
    std::vector<int> stk;//存储同一个SCC
    std::vector<int> dfn, low, bel;//dfn : dfs的时间戳 low : 子树能跳到的最上方的点 bel : 结点位于哪块强连通分量上 
    int cur, cnt;
    
    SCC() {}
    SCC(int n) {
        init(n);
    }
    
    void init(int n) {
        this->n = n;
        adj.assign(n, {});
        dfn.assign(n, -1);
        low.resize(n);
        bel.assign(n, -1);
        stk.clear();
        cur = cnt = 0;
    }
    
    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }
    
    void dfs(int x , int fa) {
        dfn[x] = low[x] = cur++;
        stk.push_back(x);
        
        for (auto y : adj[x]) {
        	if(y == fa) continue;
            if (dfn[y] == -1) {
                dfs(y , x);
                low[x] = std::min(low[x], low[y]);
            } else if (bel[y] == -1) {
                low[x] = std::min(low[x], dfn[y]);
            }
        }
        
        if (dfn[x] == low[x]) {
            int y;
            do {
                y = stk.back();
                bel[y] = cnt;
                stk.pop_back();
            } while (y != x);
            cnt++;
        }
    }
    
    std::vector<int> work() {
        for (int i = 0; i < n; i++) {
            if (dfn[i] == -1) {
                dfs(i , -1);
            }
        }
        return bel;
    }
};
struct HLD {//轻重链剖分
    int n;
    std::vector<int> siz, top, dep, parent, in, out, seq , val;//子树大小 所在重链的顶部节点 深度 父亲 子树DFS序的起点 子树DFS序的终点
    std::vector<std::vector<int>> adj;
    int cur = 1;
    HLD() {}
    HLD(int n) {
        init(n);
    }
    void init(int n) {
        this->n = n;
        siz.resize(n);
        top.resize(n);
        dep.resize(n);
        parent.resize(n);
        in.resize(n);
        out.resize(n);
        seq.resize(n);
        val.assign(n , 0);
        cur = 0;
        adj.assign(n, {});
    }
    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    void work(int root = 1) {
        top[root] = root;
        dep[root] = 0;
        parent[root] = -1;
        dfs1(root);
        dfs2(root);
    }
    void dfs1(int u) {
        if (parent[u] != -1) {
            adj[u].erase(std::find(adj[u].begin(), adj[u].end(), parent[u]));
        }
        siz[u] = 1;
        for (auto &v : adj[u]) {
            parent[v] = u;
            dep[v] = dep[u] + 1;
            dfs1(v);
            siz[u] += siz[v];
            if (siz[v] > siz[adj[u][0]]) {
                std::swap(v, adj[u][0]);
            }
        }
    }
    void dfs2(int u) {
        in[u] = ++cur;
        seq[in[u]] = u;
        for (auto v : adj[u]) {
            top[v] = v == adj[u][0] ? top[u] : v;
            dfs2(v);
            val[u] += val[v];
        }
        out[u] = cur;
    }
    int lca(int u, int v) {
        while (top[u] != top[v]) {
            if (dep[top[u]] > dep[top[v]]) {
                u = parent[top[u]];
            } else {
                v = parent[top[v]];
            }
        }
        return dep[u] < dep[v] ? u : v;
    }
    
    int dist(int u, int v) {
        return dep[u] + dep[v] - 2 * dep[lca(u, v)];
    }
    
    int jump(int u, int k) {
        if (dep[u] < k) {
            return -1;
        }
        
        int d = dep[u] - k;
        
        while (dep[top[u]] > d) {
            u = parent[top[u]];
        }
        
        return seq[in[u] - dep[u] + d];
    }
    
    bool isAncester(int u, int v) {//是否为祖先
        return in[u] <= in[v] && in[v] < out[u];
    }
    
    int rootedParent(int u, int v) {
        std::swap(u, v);
        if (u == v) {
            return u;
        }
        if (!isAncester(u, v)) {
            return parent[u];
        }
        auto it = std::upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) {
            return in[x] < in[y];
        }) - 1;
        return *it;
    }
    int rootedSize(int u, int v) {
        if (u == v) {
            return n;
        }
        if (!isAncester(v, u)) {
            return siz[v];
        }
        return n - siz[rootedParent(u, v)];
    }
    
    int rootedLca(int a, int b, int c) {
        return lca(a, b) ^ lca(b, c) ^ lca(c, a);
    }
};
void solve() 
{
	int n , m;
	cin >> n >> m;
	SCC scc(n + 5);
	pair<int,int>p[m];
	for(int i = 0 ; i < m ; i ++){
		int u , v;
		cin >> u >> v;
		scc.addEdge(u , v);
		scc.addEdge(v , u);
		p[i].x = u;
		p[i].y = v;
	}
	vector<int>v = scc.work();
	int ma = -1;
	for(int i = 1 ; i <= n ; i ++){
		ma = max(ma , v[i]);
	}
	HLD hld(ma + 5);
	for(int i = 0 ; i < m ; i ++){
		int u = v[p[i].x] , x = v[p[i].y];
		if(u == x) continue;
		hld.addEdge(u , x);
	}
	for(int i = 1 ; i <= n ; i ++){
		hld.val[v[i]]++;
	}
	hld.work();
	int ans = n * (n - 1) / 2;
	for(int i = 2 ; i <= ma ; i ++){
		ans = min(ans , hld.val[i] * (hld.val[i] - 1) / 2 + (n - hld.val[i]) * (n - hld.val[i] - 1) / 2);
	}
	cout << ans << endl;
}            
signed main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout.precision(10);
    int t=1;
	cin>>t;
    while(t--)
    {
    	solve();
    }
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python魔法参数:深入解析*args和**kwargs的强大用途

目录 引言 基础概念解析 *args:处理位置参数 **kwargs:处理关键字参数 *args和**kwargs的实际应用场景 1. 函数装饰器中使用*args和**kwargs 2. 类构造函数中使用*args和**kwargs 3. API调用中使用**kwargs 与其他参数类型的结合使用 结合默认参数 位置参数与关键…

第5讲:建立自己的C函数库,js调用自己写的C/C++函数,并包含依赖C/C++第三方静态库。

在javascript中&#xff0c;Array有很多内置的功能&#xff0c;比如Array.map&#xff0c;Array.filter&#xff0c;Array.find等等&#xff0c;能用内置的功能就用内置的功能&#xff0c;最好不要自己实现一套&#xff0c;因为底层调用的可能压根就不是js语言本身&#xff0c;…

从零开始了解GPT-4o模型:它是如何工作的?

人工智能&#xff08;AI&#xff09;技术正以惊人的速度发展&#xff0c;其中最引人注目的是OpenAI发布的GPT-4o模型。作为GPT系列的新成员&#xff0c;GPT-4o在多模态输入处理和响应速度上取得了重大进展。本文将深入探讨GPT-4o的工作原理&#xff0c;帮助您全面了解这一尖端A…

【教程】DPW 325T FPGA板卡程序下载与固化全攻略

到底什么是固化&#xff1f;&#xff1f;&#xff1f; 在开发板领域&#xff0c;"固化"通常指的是将软件或操作系统的镜像文件烧录&#xff08;Flash&#xff09;到开发板的存储介质上&#xff0c;使其成为开发板启动时加载的系统。这个过程可以确保开发板在启动时能…

Java日志 - JUL

一、JUL学习总结 &#xff08;1&#xff09;总结 JDK自带的日志系统中已经为我们创建了一个顶层的RootLogger&#xff0c;可以针对这个顶层的RootLogger设置多个Handler&#xff08;如ConsoleHandler, FileHandler等&#xff09;&#xff0c;如果想在控制台输出debug级别以上的…

生命在于学习——Python人工智能原理(2.6.1)

六 Python的文件系统 6.1 打开文件 在Python中&#xff0c;可以使用内置的open函数来打开文件&#xff0c;open函数的基本语法如下&#xff1a; file open(file_name, moder, buffering-1, encodingNone, errorsNone, newlineNone, closefdTrue, openerNone)参数说明&#…

IIS在Windows上的搭建

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 目录 一 概念&#xff1a; 二网络…

Mozilla Firefox正在尝试集成ChatGPT等帮助用户总结或改写网页内容

Mozilla基金会开启了一项新计划&#xff1a;在接下来几个月里尝试在Firefox浏览器里集成 ChatGPT 等 AI 服务&#xff0c;帮助用户在网页上总结内容或者改写内容等。Firefox浏览器集成的 AI 服务包括但不限于 ChatGPT、Google Gemini、HuggingChat 等&#xff0c;当然这并不是把…

vue3import的插件全局引入

webpack 的引入 npm install -D unplugin-auto-import const AutoImport require(unplugin-auto-import/webpack).default;configureWebpack: {devtool: source-map,module: {rules: [{test: /\.mjs$/,include: /node_modules/,type: javascript/auto}],}, plugins: [Aut…

超详细的Pycharm使用虚拟环境搭建Django项目并创建新的虚拟环境教程

一、什么是虚拟环境&#xff1f; 通过软件虚拟出来的开发环境&#xff0c;不是真实存在的&#xff0c;一般在多套环境开发时会用到。 二、为什么要使用虚拟环境&#xff1f; 虚拟环境为不同的项目创建不同的开发环境&#xff0c;开发环境内所有使用的工具包互不影响。比如项…

安全工具 | BurpSuite安装使用(保姆级教程!)

Burp Suite下载,破解,代理web,代理模拟器 (一)为Burp Sutie下载运行执行脚本环境(Java) 1.Java官网下载地址&#xff1a;https://www.oracle.com/java/technologies/ 下载Java SE 17.0.8(LTS) 备注&#xff1a;1.2023版Burp Suite 完美的运行脚本的环境是Java17 2.Java8不支持…

matlab中函数meshgrid

(1) 二维网格 [X,Y] meshgrid(x,y) 基于向量 x 和 y 中包含的坐标返回二维网格坐标。X 是一个矩阵&#xff0c;每一行是 x 的一个副本&#xff1b;Y 也是一个矩阵&#xff0c;每一列是 y 的一个副本。坐标 X 和 Y 表示的网格有 length(y) 个行和 length(x) 个列。 x 1:3; y…

昇思25天学习打卡营第8天 | 保存与加载 使用静态图加速

保存与加载 在训练网络模型的过程中&#xff0c;实际上我们希望保存中间和最后的结果&#xff0c;用于微调&#xff08;fine-tune&#xff09;和后续的模型推理与部署&#xff0c;下面是介绍如何保存与加载模型。 先定义一个模型用&#xff1a; import numpy as np import m…

grpc学习golang版( 五、多proto文件示例)

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 文章目录 一、前言二、定义proto文件2.1 公共proto文件2.2 语音唤醒proto文件2.3 人脸唤醒proto文件2.4 生成go代码2.…

最佳Google Chrome扩展和Mozilla Firefox扩展自动解决验证码

在这个信息爆炸的时代&#xff0c;我们每天都要处理大量的在线内容&#xff0c;验证码已成为不可避免的挑战。尽管它们旨在保护网站安全&#xff0c;但也常常成为我们获取信息的障碍。那么&#xff0c;有没有更简单的方法绕过这些验证码呢&#xff1f;答案是肯定的。通过使用一…

恭喜朱雀桥的越南薇妮她牌NFC山竹汁饮料,成为霸王茶姬奶茶主材

朱雀桥NFC山竹汁饮料&#xff1a;荣登霸王茶姬奶茶主材&#xff0c;非遗传承的天然之选 近日&#xff0c;据小编了解到&#xff1a;霸王茶姬欣喜地宣布&#xff0c;成功与朱雀桥达成合作越南薇妮她VINUT牌NFC山竹汁饮料。这款商超产品凭借其卓越的品质与独特的口感&#xff0c…

小项目——MySQL集训(学生成绩录入)

ddl语句 -- 创建学生信息表 CREATE TABLE students (student_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 学生ID,name VARCHAR(50) NOT NULL COMMENT 学生姓名,gender ENUM(男, 女) NOT NULL COMMENT 性别,class VARCHAR(50) NOT NULL COMMENT 班级,registration_date DATE CO…

【Termius】详细说明MacOS中的SSH的客户端利器Termius

希望文章能给到你启发和灵感~ 如果觉得有帮助的话,点赞+关注+收藏支持一下博主哦~ 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境二、软件的安装2.1 Termius界面介绍2.1.1 Hosts 主机列表2.1.2 SFTP 文件传输2.1.3 Port ForWarding 端口转发2.1.4 Snippets 片…

想要打造高效活跃的私域社群,这些技巧要知道

对一些企业来说“做社群等于做私域”。 在腾讯提到的私域转化场景中&#xff0c;社群与小程序、官方导购三者并列。 社群连接着品牌和群内用户。品牌通过圈住更多用户&#xff0c;来持续免费触达用户实现变现&#xff0c;用户则是从品牌方手中直接获取更多服务和优惠。那么&a…

LabVIEW中卡尔曼滤波的作用与意义

卡尔曼滤波&#xff08;Kalman Filter&#xff09;是一种在控制系统和信号处理领域广泛应用的递推滤波算法&#xff0c;能够在噪声环境下对动态系统的状态进行最优估计。其广泛应用于导航、目标跟踪、图像处理、经济预测等多个领域。本文将详细介绍卡尔曼滤波在LabVIEW中的作用…