[2021-06-19] 提高组新手副本Ⅱ(联网,欧几里得,分解树,开关灯)

文章目录

  • 考试心路历程
  • 联网
    • title
    • solution
    • code
  • 欧几里得
    • title
    • solution
    • code
  • 分解树
    • title
    • solution
    • code
  • 开关灯
    • title
    • solution
    • code

考试心路历程

在这里插入图片描述

佛了佛了,caocaocaocaocaocao 人直接炸嗨升天

并查集直接送走200200200分!!!我屮艸芔茻

T1二分检查直接离开——好家伙没想到没死在精度上,直接鞭尸并查集

之前还嘲笑香香mm,原来SB竟是我自己

T2构造不出来,拿了基础的部分分

T3并查集反着做,排序方法错了,不说了不说了,懂的都懂

T4敲了链的部分分但是没过,谁知道呢??

害!

总之这一场发挥非常离谱,从来没有这么炸过,可以说,题目又不难
在这里插入图片描述

联网

title

题目描述

有n个无线电信号站,每个无线电发射站的发射半径都必须相等,你可以统一设置它们半径。发射半径越长,则花费越大。如果两个无线电发射站能覆盖同一个点,则它们能够联网。如果A与B能联网,B与C能联网,则A,C也能联网。现在告诉你这n个无线电发射站的坐标,你需要让它们连成一个网络,请问最小的发射半径是多少?

输入格式

第一行包含一个整数nnn,表示无线电信号站的数量。

接下来有n行,每行包含两个整数xi,yix_i,y_ixi,yi,表示发射站的坐标

输出格式

一个实数,表示最小发射半径,保留7位小数。

输入样例1

2
1 1
2 2

输出样例1

0.7071068

输入样例2

7
2 3
3 4
4 5
0 1
3 1
4 2
1 5

输出样例2

1.4142135

输入样例3

4
2020 20
20 2020
2020 2020
20 20

输出样例3

1000.0000000

solution

二分距离,暴力检查,用并查集判断是否联通

最后注意并查集不要打错了,不然骨灰挥洒

code

#include <cmath>
#include <cstdio>
#define eps 1e-7
#define maxn 1005
struct node {double x, y;
}net[maxn];
int n;
int f[maxn];void MakeSet() {for( int i = 1;i <= n;i ++ ) f[i] = i;
}int FindSet( int x ) {return x == f[x] ? x : f[x] = FindSet( f[x] );
}void UnionSet( int u, int v ) {int fu = FindSet( u ), fv = FindSet( v );f[fv] = fu;
}double dis( int i, int j ) {return sqrt( ( net[i].x - net[j].x ) * ( net[i].x - net[j].x ) + ( net[i].y - net[j].y ) * ( net[i].y - net[j].y ) );
}bool check( double x ) {MakeSet();for( int i = 1;i <= n;i ++ )for( int j = i + 1;j <= n;j ++ )if( dis( i, j ) <= x * 2 )UnionSet( i, j );for( int i = 1;i < n;i ++ )if( FindSet( i ) != FindSet( i + 1 ) ) return 0;return 1;
}int main() {scanf( "%d", &n );for( int i = 1;i <= n;i ++ )scanf( "%lf %lf", &net[i].x, &net[i].y );double l = 0, r = 1e9, ans;while( r - l > eps ) {double mid = ( l + r ) / 2;if( check( mid ) ) ans = mid, r = mid;else l = mid;}printf( "%.10f\n", ans );return 0;
}

欧几里得

title

我们知道辗转相除法,现在给一个类似与辗转相除的函数R(a,b)R(a,b)R(a,b),定义如下
R(a,b)={R(b,a)a<bR(a,b)=\{ R(b,a)a<b R(a,b)={R(b,a)a<b

给你两个整数g,hg,hg,h,请你找两个整数a,ba,ba,b,使得它们满足gcd⁡(a,b)=g,R(a,b)=h\gcd(a,b)=g,R(a,b)=hgcd(a,b)=g,R(a,b)=h

输入格式

第一行包含一个整数t(1≤t≤40)t(1\le t\le 40)t(1t40),表示测试数据的组数。

接下来有ttt行,每行包含两个正整数g,hg,hg,h

输出格式

包含ttt行,每行包含两个整数a,ba,ba,b,表示符合上述条件的整数。

保证答案不超过1e181e181e18,可以证明一定有解。

1≤g≤200000,2≤h≤2000001\le g\le 200000,2\le h\le 2000001g200000,2h200000

输入样例1

1
1 4

输出样例1

99 23

输入样例2

2
3 2
5 5

输出样例2

9 39
5 5

solution

最后的答案长相一定是R(h,1)R(h,1)R(h,1),也就是说之前的每一次一定满足min(a,b)≥hmin(a,b)\ge hmin(a,b)h

那么每次都至少会让max(a,b)max(a,b)max(a,b)缩成原来的1h\frac{1}{h}h1

假设操作进行了kkk次,那么构造得a∈[hk,2∗hk)a∈[h^k,2*h^k)a[hk,2hk)

又满足是ggg的倍数

b=g∗⌈hkg⌉,a=b∗h+gb=g*\lceil\frac{h^k}{g}\rceil,a=b*h+gb=gghk,a=bh+g

code

#include <cmath> 
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
int T, g, h;signed main() {scanf( "%lld", &T );while( T -- ) {scanf( "%lld %lld", &g, &h );int b = h;while( b <= g ) b *= h;if( b % g ) b += g - ( b % g );int a = b * h + g;printf( "%lld %lld\n", a, b );}return 0;
}

分解树

title

题目描述

有一棵树,有nnn个顶点,每个节点都有权值,现在你要将每条边都断开,你可以选择断开的顺序,最终的代价可能是不同的。断开一条边的代价为该边连接的两个连通块中各取一个最大权值的顶点之和。请问最后将所有边都断开的最小代价是多少?n≤1e5n\le 1e5n1e5

输入格式

第一行包含一个整数nnn,表示有nnn个顶点。

第二行包含nnn个整数,表示顶点iii的权值

接下来有n−1n-1n1行,每行两个整数a,ba,ba,b,表示点aaa与点bbb相连。

输出格式

一个整数,表示最小的代价

输入样例1

3
1 2 3
1 2
2 3

输出样例1

8

输入样例2

4
2 2 3 2
1 3
3 2
4 3

输出样例2

15

输入样例3

5
5 2 3 1 4
2 1
3 1
2 4
2 5

输出样例3

26

solution

法一:反其道而行

相当于是加边,构成一棵树,加边操作为两边连通块各自的最大值之和,求最小花费

显然,肯定是边花费越小越先加

边按照连接的两个连通块的最大值从小到大排序(PS:不是和从小到大)

因为两条边先后合并顺序不同,只会是最大值加的不同

法二:找结论

独立计算每个点会产生多少次贡献,显然是从最大点值的边开始断着走

断开一条边时,设该边的两个点为xi,yix_i,y_ixi,yi,设txi>tyit_{x_i}>t_{y_i}txi>tyi,则xix_ixi会作为当前的最大点算一次贡献,而第二大点也会算一次贡献

所有点(除了全局最大点之外)都有且仅有一次机会成为第二最大点被算一次贡献

因为算了贡献一次后,他就是他所在连通块中的最大点了,永远不可能再成为第二最大点

所以最终的贡献为:∑i<n(max(txi,tyi))+∑i≤nti−maxi≤n(ti)\sum_{i<n}(max(t_{x_i},t_{y_i}))+\sum_{i \leq n}t_i-max_{i\leq n}(t_i)i<n(max(txityi))+intimaxin(ti)

code

#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 100005
#define int long long
struct node {int u, v, w;node(){}node( int U, int V, int W ) {u = U, v = V, w = W;}bool operator < ( node &t ) const {return w < t.w;}
};
vector < node > G;
int n, ans;
int val[maxn], f[maxn];void MakeSet() {for( int i = 1;i <= n;i ++ ) f[i] = i;
}int FindSet( int x ) {return x == f[x] ? x : f[x] = FindSet( f[x] );
}void UnionSet( int u, int v ) {u = FindSet( u ), v = FindSet( v );ans += val[u] + val[v];f[v] = u;val[u] = max( val[u], val[v] );
}signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ )scanf( "%lld", &val[i] );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%lld %lld", &u, &v );G.push_back( node( u, v, max( val[u], val[v] ) ) );}sort( G.begin(), G.end() );MakeSet();for( int i = 0;i < G.size();i ++ )UnionSet( G[i].u, G[i].v );printf( "%lld\n", ans );return 0;
}

开关灯

title

题目描述

nnn盏灯,组成了一棵树,一开始有些灯是开着的,有些灯是关着的。你可以从任一盏灯开始,沿着树上的路径游走,你经过的地方,灯都会改变状态。你可以重复经过某一盏灯,每经过它一次,它的状态都会发生改变。你的目标是要将所有灯都变成开的状态。请问,你的游走轨迹上的最少的灯数是多少?如果你重复经过一盏灯,则它要算多次。

输入格式

第一行一个整数nnn。 接下来是一个nnn位的01串,表示灯的开关状态,000表示关,111表示开。 再接下来有 行,每行两个整数a,ba,ba,b,表示aaabbb相连。

输出格式

一个整数,表示答案。

输入样例1

3
010
1 2
2 3

输出样例1

4

输入样例2

5
00000
1 2
2 3
2 4
3 5

输出样例2

7

输入样例3

5
00100
1 2
2 3
2 4
3 5

输出样例3

8

solution

题解

大部分注释在代码里

code

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 500005
vector < int > G[maxn];
int n;
char s[maxn];
bool g[maxn];
int t[3][2];
int f[maxn][3][2];void dfs( int u, int fa ) {g[u] = s[u] - '0';for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa ) continue;else dfs( v, u ), g[u] &= g[v];}
}void solve( int u, int fa ) {
//f(u,i,j):subtree_u has i=0/1/2 endpoints of the path. at the beginning u is j=0/1	
//the minicost to make nodes of subtree_u all be 1(lights all open)f[u][0][0] = 1;for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if( v == fa || g[v] ) continue;else solve( v, u );//subtree_v are all lighted just continueint ss = s[v] - '0';for( int j = 0;j <= 2;j ++ )for( int k = 0;k <= 1;k ++ ) {/*endpoints both belong to u_subtreev_subtree all rightu_subtree all right(except u itself)one endpoint -> u(wrong->right)cost 1*/t[j][k] = f[u][j][k ^ 1] + f[v][0][ss] + 1;/*endpoints both belong to u_subtreev_subtree all right(except v itself)u_subtree all rightone endpoint -> u(right->wrong) -> v(wrong->right) -> u(wrong->right)cost 3*/t[j][k] = min( t[j][k], f[u][j][k] + f[v][0][ss ^ 1] + 3 );if( j > 0 ) {/*one endpoint belongs to v_subtreethe other belongs to u_subtree or other subtrees(don't include u_subtree)v_subtree and u_subtree all rightjust f(u) plus f(v)*/t[j][k] = min( t[j][k], f[u][j - 1][k] + f[v][1][ss] );/*one endpoint belongs to v_subtreethe other belongs to u_subtree or other subtrees(don't include u_subtree)v_subtree and u_subtree all right(except u and v)we need to touch u and vcost another 2*/t[j][k] = min( t[j][k], f[u][j - 1][k ^ 1] + f[v][1][ss ^ 1] + 2 );}if( j > 1 ) {/*endpoints both belong to v_subtreev_subtree all right(except v itself)u_subtree all rightwe need tp touch vone endpoint -> v(wrong->right)cost 1*/t[j][k] = min( t[j][k], f[u][j - 2][k] + f[v][2][ss ^ 1] + 1 );/*endpoints both belong to v_subtreev_subtree all rightu_subtree all right(except u itself)one endpoint -> v(right->wrong) -> u(wrong->right) -> v(wrong->right)cost 3*/t[j][k] = min( t[j][k], f[u][j - 2][k ^ 1] + f[v][2][ss] + 3 );}}for( int j = 0;j <= 2;j ++ )for( int k = 0;k <= 1;k ++ )f[u][j][k] = t[j][k];}for( int j = 1;j <= 2;j ++ )for( int k = 0;k <= 1;k ++ )f[u][j][k] = min( f[u][j][k], f[u][j - 1][k] );//comparison choose a smaller one 
}int main() {scanf( "%d %s", &n, s + 1 );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u ); }int rt = -1;for( int i = 1;i <= n;i ++ )if( s[i] == '0' ) {rt = i;break;} else;if( ~ rt ) {dfs( rt, 0 );printf( "NONO\n" );memset( f, 0x3f, sizeof( f ) );solve( rt, 0 );printf( "%d\n", f[rt][2][0] );}else printf( "0\n" );return 0;
} 

在这里插入图片描述

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

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

相关文章

在.NET Core中设计自己的服务宿主(Service Hosting)框架

很多时候我们都会有设计一个后台服务的需求&#xff0c;比如&#xff0c;传统的Windows Service&#xff0c;或者Linux下的守护进程。这类应用的一个共同特点就是后台运行&#xff0c;并且不占用控制台界面。通常情况下&#xff0c;后台服务在提供服务时&#xff0c;会通过日志…

CF1131 G. Most Dangerous Shark(DP+单调栈优化)

文章目录problemsolutioncodeproblem solution dpi:dp_i:dpi​: 前iii个多米诺骨牌全都倒下的最小花费 li,ril_i,r_ili​,ri​分别表示第iii个多米诺骨牌倒下时所能波及到的最左/右位置 往左倒&#xff0c;则[li,i)[l_i,i)[li​,i)内的牌都可以选择性地先推倒 dpimin⁡{dpjcos…

Cat Virus

Cat Virus 题意&#xff1a; 让你构造一颗树&#xff0c;要求如果一个点为黑&#xff0c;其子树全为黑&#xff0c;白点任意&#xff0c;现在让你构造一棵树&#xff0c;使其染色方案数为K&#xff0c;节点尽可能少 题解&#xff1a; 首先画出k<9的全部情况&#xff0c;并…

微软发布XAML Studio工具:快速构建UWP XAML原型

IT之家1月30日消息 微软车库的最新项目XAML Studio已经在Windows 10应用商店上架&#xff0c;将帮助开发人员快速构建UWP XAML原型&#xff0c;以后可以轻松地将其复制到Visual Studio中。它将允许开发人员实时预览他们的XAML代码&#xff0c;并与结果进行交互&#xff0c;就像…

.NET Core 3 Preview 2发布,C#8更强大的模式匹配

.NET Core 3 Preview 2 发布了&#xff0c;此版本主要带来了 C# 8 相关的新功能&#xff0c;C# 8 Preview 2 是 .NET Core 3 SDK 的一部分。C# 8 中使用模式进行更多操作&#xff0c;主要特性包括&#xff1a;using 声明改变需要缩进代码的方式&#xff0c;现在可以编写以下代码…

CF407 E. k-d-sequence(线段树+单调栈)

文章目录CF407 E. k-d-sequenceproblemsolutioncodeCF407 E. k-d-sequence problem solution special case&#xff0c;d0d0d0&#xff0c;相当于寻找最长的一段数字相同的区间 other case&#xff0c;如果要满足公差为ddd等差序列 区间内每个数在模ddd意义下同余每个数互不…

D. Binary Literature

D. Binary Literature 题意&#xff1a; 给三个长度为2 * n的01串&#xff0c;让你构造一个长度小于3 * n的字符串&#xff0c;使得这个串至少包含两个01串 题解&#xff1a; 很巧妙的构造题 三个指针分别指向三个串&#xff0c;因为是01串&#xff0c;所以一定存在两个字符…

安逸:鼠绘《诗与远方》

【作品名称】《诗与远方》【作者介绍】徐安&#xff08;笔名安逸&#xff0c;常州&#xff09;&#xff0c;PPT专家&#xff0c;鼠绘专家。平面设计专业&#xff0c;6年PPT设计经验&#xff1b;历届江苏省PPT制作大赛一等奖获得者&#xff0c;PA口袋动画重要合作人。PPT动画制作…

[HNOI2016]网络(树链剖分+线段树+大根堆)

[HNOI2016]网络 problem solution 另辟蹊径&#xff0c;不把交互请求赋在新增路径上&#xff0c;反而把交互请求赋在树上除去该请求路径覆盖点的其它点上 显然&#xff0c;路径问题树剖是非常可以的、 那么一个点上的信息就表示所有不经过该点的交互请求&#xff0c;用堆…

IdentityServer4实战 - JWT Token Issuer 详解

一.前言本文为系列补坑之作&#xff0c;拖了许久决定先把坑填完。下文演示所用代码采用的 IdentityServer4 版本为 2.3.0&#xff0c;由于时间推移可能以后的版本会有一些改动&#xff0c;请参考查看&#xff0c;文末附上Demo代码。本文所诉Token如无特殊说明皆为 JWT Token。众…

P3834 【模板】可持久化线段树 2(整体二分做法)

P3834 【模板】可持久化线段树 2&#xff08;主席树&#xff09; 我们详细讲讲这个整体二分如何求区间第k小 我们都知道二分可以求出区间里某个想要的值&#xff0c;如果有很多询问&#xff0c;我们对每个询问都进行二分&#xff0c;复杂度就是O(QNlog(1e9))铁超&#xff0c;那…

胡浩:人人能学的AI《从零开始机器学习》苏州.NET俱乐部课程分享

【课程名称】《从零开始机器学XI》【老师介绍】胡浩&#xff0c;微软最有价值专家&#xff08;MVP&#xff0c;十余届多方向&#xff09;&#xff0c;微软技术大会讲师。云、数据中心基础架构、全栈虚拟化、企业移动管理等领域的架构师及顾问。AI/ML等新技术的爱好者&#xff0…

IdentityServer4实战 - 与API单项目整合

一.前言我们在实际使用 IdentityServer4 的时候&#xff0c;可能会在使用 IdentityServer4 项目添加一些API&#xff0c;比如 找回密码、用户注册、修改用户资料等&#xff0c;这些API与IdentityServer4怎么共存在一个项目呢&#xff1f;二.整合1.首先在 Startup.cs 中添加 Ide…

[HDU 6157]The Karting(DP)

[HDU 6157]The Karting description solution 先用前缀和求出di:1→id_i:1\rightarrow idi​:1→i 的距离 前缀和满足&#xff1a;若在iii点进行方向改变&#xff0c;则iii产生的贡献是一定的&#xff0c;可以先累计贡献 也就是说真正的路径怎么走&#xff0c;我们是不关心…

.NET 开源简史

现在在微软开发开源软件是很一件正常的事情——但在 2007 年&#xff0c;当时我刚加入微软&#xff0c;那时候可不是这么一回事。微软花了好几年时间才找到正确的方向&#xff0c;让微软这艘大船顺着开源之风向前航行。现在回头远望过去那些曾经面临的挑战&#xff0c;我们一笑…

P2617 Dynamic Rankings(整体二分)

P2617 Dynamic Rankings 题意: 待修改的区间最值问题 题解&#xff1a; 整体二分天然带有修改性 整体二分做不带修改的区间最值—>看这里 现在待修改&#xff0c;我们可以将第l位修改为x&#xff0c;因为我们是用树状数组来维护的&#xff0c;所以把这个过程拆分成将第l个…

[LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心+贪心)

[LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相 description solution 一个到所有节点距离和最小的节点 ⇔\Leftrightarrow⇔ 树的重心&#xff08;满足最重的儿子最轻&#xff0c;每个儿子siz≤n2\le\frac{n}{2}≤2n​&#xff09; 显然原树的重心答案为0 对于点iii&am…

由优劣语言之争引起的思考

由优劣语言之争引起的思考#欲使其灭亡&#xff0c;必使其疯狂昨天上午由阿里云中间件公众号和架构师小秘圈公众号发布的一篇文章《天天敲代码会使人变聪明么》在.net开发者中掀起了一阵巨浪&#xff0c;文章中提到的语言的先进与落后之争让基于.net开发者们义愤填膺&#xff0c…

[LOJ #521]「LibreOJ β Round #3」绯色 IOI(抵达)(结论)

#521. 「LibreOJ β Round #3」绯色 IOI&#xff08;抵达&#xff09; description solution 因为点的庇护所不能为自身&#xff0c;题目背景在树上&#xff0c;有结论一定是两个相邻点互为庇护所 所以树一定要能两两完美匹配才有解 判断完有解后就是构造解了&#xff0c;…

微软是如何使用 C# 重写 C# 编译器并将其开源的

Roslyn 是 C# 和 Visual Basic.NET 开源编译器的代号。这篇文章将介绍它是如何从微软过去的十年至暗时刻走出来&#xff0c;成为开源跨平台的 C# 和 VB 公共语言引擎。我于 2005 年加入微软&#xff0c;也就是在.NET 2.0 发布之前&#xff0c;当时微软内部已经开始在讨论 Rosly…