Codeforces Round #542 题解
Codeforces Round #542
abstract
I决策中的独立性,
II联通块染色板子
IIIVoronoi diagram O(N^2 logN)
VI环上距离分类讨论加取模,最值中的决定性元素
V代数构造
B
题意
2n个数排成一行,1..n各出现两次,两个人分别从1按顺序走到n(每个数只能被一个人路过),问他们两个人的距离和的最小值(两个数之间的距离等于他们位置(下标)值差)?
题解
将每个数的两个位置用pair存起来(eg : pos[1].x , pos[1].y)。
首先我们发现两个人的选择其实并不独立,如果一个人选择了一条路,另一个人的路也就确定了。其次我们发现每两个数之间的路径是相互独立的。
所以对于每一段 i to i+1 我们只要取min(abs(pos[i + 1].x - pos[i].x) + abs(pos[i + 1].y - pos[i].y), abs(pos[i + 1].x - pos[i].y) + abs(pos[i + 1].y - pos[i].x))即可。 最后求和
代码
//头文件省略
cin >> n;
rep(i, 1, 2 * n) {
int a;
cin >> a;
if (pos[a].x == 0)pos[a].x = i;
else pos[a].y = i;
}
ll ans = pos[1].x + pos[1].y - 2;;
rep(i, 1, n - 1)c[i] = min(abs(pos[i + 1].x - pos[i].x) + abs(pos[i + 1].y - pos[i].y), abs(pos[i + 1].x - pos[i].y) + abs(pos[i + 1].y - pos[i].x));
rep(i, 1, n-1)ans += c[i];
cout << ans;
C
题意
求网格图上联通块之间的最短距离平方。
sample input
5
1 1
5 5
00001
11111
00111
00110
00110
sample input
10
其中0代表陆地,1代表海洋
题解
直接跑一遍联通块染色,然后暴力O(n^4)就能过。
优化的方法是取边界,O(n^3)。
最优解是Voronoi diagram O(N^2 logN)
代码
#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define MD(x) x%=mod
#define FAST_IO ios_base::sync_with_stdio(false); cin.tie(nullptr)
#define precise(x) fixed << setprecision(x)
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 256;;
const int maxn = 2e5+2;
const int INF = 1e9;
const db eps = 1e-7;
const int mod = 1e9 + 7;
//a[maxn], b[maxn];
int A[maxn];
char mmp[55][55];
int color[55][55];
int n,m;
int dir[4][2] = { 0,1 ,1,0, 0,-1, -1,0 };
int colornum = 0;
void dfs(int x, int y) {
if (color[x][y])return;
color[x][y] = colornum;
rep(i, 0, 3) {
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if (dx<1 || dx>n || dy<1 || dy>n)continue;
if(mmp[dx][dy]=='0')dfs(dx, dy);
}
}
void bfs(int x, int y) {
queue<pair<int, int> >Q;
Q.push({ x,y });
color[x][y] = colornum;
while (!Q.empty()) {
auto v = Q.front();
Q.pop();
rep(i, 0, 3) {
int dx = v.first + dir[i][0];
int dy = v.second + dir[i][1];
if (color[dx][dy])continue;
if (dx<1 || dx>n || dy<1 || dy>n)continue;
if (mmp[dx][dy] == '0')Q.push({ dx,dy }),color[dx][dy]=colornum;
}
}
}
int main() {
FAST_IO;
cin >> n;
int r1, c1, r2, c2;
cin >> r1 >> c1 >> r2 >> c2;
rep(i, 1, n)cin >> mmp[i] + 1;
rep(i, 1, n)rep(j, 1, n) if(mmp[i][j]=='0'){
if (!color[i][j]) {
colornum++;
bfs(i, j);
}
}
int ans = 1e9;
if (color[r1][c1] == color[r2][c2])ans = 0;
else {
rep(i, 1, n)rep(j, 1, n)if (color[i][j] == color[r1][c1]) {
rep(ii, 1, n)rep(jj, 1, n)if (color[ii][jj] == color[r2][c2]) {
ans = min(ans, (i - ii)*(i - ii) + (j - jj)*(j - jj));
}
}
}
cout << ans << endl;
cin >> n;
}
D
题意
有一个n个结点的环,每个结点上有一些糖果,每个糖果都有一个想要到达的结点,你现在从某个结点出发顺时针走,每次经过一个结点只能带一个糖果,问从某点出发最少走多少路程可以把所有糖果运送到它们想要到达的结点? 出发点取遍1到n。
题解
我们发现从某结点出发拿一个糖果,最坏情况下走一圈以后一定可以把它放好。而如果某节点有两颗糖果,那么至少要超过一圈才能放好。
所以 如果记所有结点中糖果数量最大值为mx,最多mx+1圈必定能全部送完。
而对一个结点来说,只有它的最后一个糖果想到达的结点决定了运完该点所有糖果总路程的长短,因此我们贪心地把路程最短的糖果留到最后拿即可。
于是问题就变成了环上求路程了,要用到取模,和分类讨论。(分类很不擅长,讨论了半天orz坑点:candy[now].size()==mx-1&&mx>1如果不加后面这个mx>1就会讨论根本没有糖果的情况,导致wa)
代码
//头文件省略
int n;
int a[maxn], b[maxn];
vector<int> candy[maxn];
int mindis[maxn];
int lastmin[maxn];
int main() {
FAST_IO;
int n, m;
cin >> n >> m;
rep(i, 1, n)mindis[i] = 1e9,lastmin[i]=0;
rep(i, 1, m) {
cin >> a[i] >> b[i];
candy[a[i]].push_back(b[i]);
mindis[a[i]] = min(mindis[a[i]], (b[i] - a[i]+n)%n);
}
int mx = 0;
rep(i, 1, n)mx = max(mx, (int)candy[i].size());
rep(i, 1, n) {
rep(j, 1, n) {
int now = (i - j+n)%n; if (now == 0)now = n;
if(candy[now].size()==mx)
lastmin[i] = max(lastmin[i],
(now - i + n) % n+mindis[now]);
else if(candy[now].size()==mx-1&&mx>1)
lastmin[i] = max(lastmin[i],
(now - i + n) % n + mindis[now]-n);
}
}
//rep(i, 1, n)cout << mindis[i] << ' '; cout << endl;
//rep(i, 1, n)cout << lastmin[i] << ' '; cout << endl;
rep(i, 1, n) {
cout <<n*(mx-1) + lastmin [i] << ' ';
}
cin >> n;
}
E
题意
构造题,给你一个问题,和一个错误算法,让你构造数据使得正确答案与错误代码答案相差k。
问题是有一个数列,a[i]<1e6,n<2e3;定义 f(l,r)=(sum[r]-sum[l-1])*(r-l+1),sum为前缀和,求max{f(l,r)} for l=1 to n, r=l to n;
错误代码是线性滑窗扫一遍,每次维护一个区间窗口,如果小于0就舍弃原区间,重新开一个新区间。如果和大于0就不停加数。
题解
代码很简单,构造很巧妙,证明很数学
考虑形如 -1 , x, x, x,...x,y的数列,共n个x,1个y都为正数(其中x都是1e6,为了满足原数列每个数<=1e6的条件),错误代码给出的解是(x*n+y)*(n+1);而正确答案应是(x*n+y-1)*(n+2)两者差为n*x+y-2 令x=1e6,n=k/x,y=k%x即可。(代数不好推了半天orz)
代码
//头文件省略
int k; cin >> k;
n = 1;
int S = -1;
int last = -1;
while (S-n+1<k) {
n++;
int delta = k-(S - n + 1) ;
if (delta <= 1e6) { last = delta; break; }
else S += 1e6;
}
cout << n << endl;
cout << -1 << ' ';
rep(i,1,n-2)cout<< 1000000 << ' ';
if (last != -1)cout << last << endl;
Codeforces Round #542 题解的更多相关文章
- Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2) 题解
Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2) 题目链接:https://codeforces.com/contest/1130 ...
- Codeforces Round 542 (Div. 2)
layout: post title: Codeforces Round 542 (Div. 2) author: "luowentaoaa" catalog: true tags ...
- Codeforces Round #556 题解
Codeforces Round #556 题解 Div.2 A Stock Arbitraging 傻逼题 Div.2 B Tiling Challenge 傻逼题 Div.1 A Prefix S ...
- Codeforces Round #569 题解
Codeforces Round #569 题解 CF1179A Valeriy and Deque 有一个双端队列,每次取队首两个值,将较小值移动到队尾,较大值位置不变.多组询问求第\(m\)次操作 ...
- Codeforces Round #557 题解【更完了】
Codeforces Round #557 题解 掉分快乐 CF1161A Hide and Seek Alice和Bob在玩捉♂迷♂藏,有\(n\)个格子,Bob会检查\(k\)次,第\(i\)次检 ...
- CFEducational Codeforces Round 66题解报告
CFEducational Codeforces Round 66题解报告 感觉丧失了唯一一次能在CF上超过wqy的机会QAQ A 不管 B 不能直接累计乘法打\(tag\),要直接跳 C 考虑二分第 ...
- Codeforces Round #542 (Div. 1) 题解
开学了住校了打不了深夜场 好难受啊QwQ A 显然对于每个起点,我们只需要贪心记录这个起点出发出去的糖果数量以及离自己最近的糖果 因为这个起点最后一次装载糖果一定是装载终点离自己最近的那个糖果 $ O ...
- Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 1) 题解
A. Toy Train 时间限制:2 seconds 内存限制:256 megabytes 题意 有编号111~n(n≤5000)n(n\le 5000)n(n≤5000)的车站顺时针呈环排列,有m ...
- Codeforces Round #542(Div. 2) CDE 思维场
C https://codeforces.com/contest/1130/problem/C 题意 给你一个\(n*m\)(n,m<=50)的矩阵,每个格子代表海或者陆地,给出在陆地上的起点终 ...
随机推荐
- DeepLearning.ai学习笔记(五)序列模型 -- week2 自然语言处理与词嵌入
一.词汇表征 首先回顾一下之前介绍的单词表示方法,即one hot表示法. 如下图示,"Man"这个单词可以用 \(O_{5391}\) 表示,其中O表示One_hot.其他单词同 ...
- 【原创】大数据基础之SPARK(9)SPARK中COLLECT和TAKE实现原理
spark中要将计算结果取回driver,有两种方式:collect和take,这两种方式有什么差别?来看代码: org.apache.spark.rdd.RDD /** * Return an ar ...
- cocos2dx-lua 文件操作
print("开始") --检查文件是否存在 local path = "ABC.txt" local fileExist = cc.FileUtils:get ...
- ALU底层方法及计算机整数加减乘除模拟
ALU是计算机CPU的核心,即 算术逻辑单元(arithmetic and logic unit)ALU有几大功能,是计算机计算最基础的功能:1.算术运算:包含加法.减法等2.逻辑运算:主要是布尔运算 ...
- C#中用ILMerge合并DLL和exe文件成一个exe文件或者DLL
ILMerge是一个将多个.NET程序集合并到一个程序集中的实用程序.它既可以作为 开源使用,也可以作为NuGet包使用. 如果您在使用它时遇到任何问题,请与我们联系.(mbarnett _at_ ...
- Java_Character类
Character类用于对单字符进行操作. 常用的方法: System.out.println(Character.isDigit('1')); // true 判断是否是一个数字字符 Syste ...
- const与#define的异同
1 作为常量时的异同 (0) 相同 两者都可以用来定义常量: #define PI 3.14159 // 常量宏 const doulbe Pi=3.14159; // 常量 (1) ...
- 网络流24题——分配问题 luogu 4014
题目链接:这里 本题是一个典型的费用流问题,可以作为费用流建图模板使用 首先看到,每个人只能做一件工作,每件工作只能做一次,一个人做某件工作有一定的收益 那么我们建立一个超级源点st和超级终点ed,然 ...
- Python面向对象之-反射
Python中一切皆对象,在Python中的反射:通过字符串的形式操作对象的属性 hasattr 判断是否有改属性或者方法,有返回True,没有返回false getattr 如果是属性获得该属性 ...
- apache基础
apache基于多域名的虚拟主机 NameVirtualHost *:80<VirtualHost *:80> DocumentRoot "/var/www/html/xk/sh ...