关闭

codeforces泛做

标签: codeforces
596人阅读 评论(0) 收藏 举报
分类:

codeforces div1的题目,一般是做B、C、D
有的A题觉得有价值也会做,死活不会的就跳了……


364

B: Connecting Universities

Problem:
一颗无根树上给出2*k个点带有标记,现在要将2*k个点两两配对,会一种方案使总距离最大,求最大的距离。
Keyword:
搜索
Analyse:
每条边应该覆盖尽量多的次数。
Solution:
每条边可以把整棵树分成两个点集。对于小的部分是某个点的子树,维护该子树的黑点个数size,那么这条边被覆盖的次数就是min(size, 2 * k - size)。

C: Break Up

Problem:
给出一个图(可能不连通),给出终点和起点,每条边上带权,现在要你删去最多两条边,使得终点与起点不连通,询问删去边的权值和的最小值,并且输出方案,多种则输出一种。
Keyword:
搜索、桥
Analyse:
1.起点与终点没路,就不用关闭任何边
2.任何一条起点到终点的简单路上肯定要关闭一条边
Solution:
先随意搜出一条从起点到终点的简单路,这条路上最多有n条边。枚举路径上的每条边,在原图上删掉这条边,然后在新图上找一条桥,这条桥一定要在起点到终点的路径上,在搜索树上多记录一个记号就可保证。然后分类讨论,时间复杂度O(nm)。

363

B: Fix a Tree

Problem:
给出n个点,每个点u向fa(u)连一条有向边,询问最少改变几个点的fa使原图变成一棵树,并输出方案,多种则输出一种。
Keyword:
搜索、并查集
Analyse:
1.联通块有三种情况:环,树,环套树
2.当一个点fa(u) == u时,存在一棵树
Solution:
先找是否存在树,存在一棵树可以直接取其根做新根,不然就在后面的联通块的环中找一个点做新根。然后,从每一个没遍历过的联通块中的随意一个点遍历一遍,就可以找出一个环上的点或者树根。无论是什么,就破坏掉,连向新根。

C: LRU

Problem:
有一个槽有k个位置,有n个物品,每个物品有一个能力值,代表他对应被选中的概率,每次操作者会选中一个物品放进槽里,当槽满的时候,会把第一个进入槽的物品挤出去,求每个物品在无限次操作后在槽中的概率。
Keyword:
状态压缩、概率
Analyse:
无限次后的结果,等价于直接选k次停下
Solution:
把题目化简成那样以后,就可以直接进行转移了。动态规划过程中按照x->y的写法较为好写,注意当一个物品概率无限小的时候,是不可能别选中的,要处理掉这样的物品。当有用物品比槽还要小的时候,槽的大小要改变。

D: Limak and Shooting Pionts

Problem:
一个无限大的二维平面图,操作者又可以按照任意顺序出现在一些点上,在每个点可以向任意方向开一枪,该方向的第一个怪物会被杀死,询问有几个怪物有可能会死。
Keyword:
搜索、几何
Analyse:
1.k <= 7,可以通过全排列去枚举顺序
2.一个怪物能被一个位置的子弹杀死,那么这两个物品中间的所有怪物都能其他位置的子弹被杀死
Solution:
先通过全排列可以得到所有的顺序。然后枚举每个怪物,判断该怪物是否能被任意一种顺序杀死。利用一个栈,每次都默认当前怪物能被当前位置的子弹杀死,那么对应的就会引入两者中间的怪物必须被杀死这一条件,并把他们入栈。某一时刻,若站内的大小比余下射击次数多即为失败。可以预处理出两者中间的怪物,需要用点积和叉积判断,若存在多余m个以上的就可以知道一定失败。
Trick:
虽然点的坐标是在int范围内,但是在点积和叉积的过程中会超过int

362

A: Lorenzo Von Matterhorn

Problem:
一个图上有很多点,点的编号从1开始,每个点i会向点2*i和点2*i+1连边。
然后有两种操作:1.u,v两点之间的最短路径上每条边加上w的大小 2.求u,v两点的最短路径(u,v <= 10^18)
Keyword:
树、STL、复杂度分析
Analyse:
1.由于该图的特殊连边,可以发现图是一颗二叉树
2.点数太多没有办法把整棵树构建出来
Solution:
因为树的形态特殊,完全可以从树上任意一点暴力操作,时间为O(logu)。那么,只需要求出(u,v)两点的最近公共祖先就行了,这部分也可以通过不断让更大的点除2来找到。因为点的编号太大,可以用map来记录每个点上面连的边权即可,这里的空间复杂度是O(qlogu)的。

B:Puzzles

Problem:
给出一颗树,每个点(2 <= u <= n)给出它的fa(u),保证fa(u) < u, 然后执行一个算法,
let starting_time be an array of length n
current_time = 0
dfs(v):
current_time = current_time + 1
starting_time[v] = current_time
shuffle children[v] randomly (each permutation with equal possibility)
// children[v] is vector of children cities of city v
for u in children[v]:
dfs(u)
最后求每个点的期望starting_time。
Keyword:
数学、期望
Analyse:
1.树上一个点u,它的starting_time与其子树下的节点无关,只和它的兄弟有关
2.树上一个点u,它的期望starting_time = fa(u)的starting_time + 某种东西
Solution:
分析到上面那样,就需要处理那个”某种东西”,不妨换一个思路。假设u已知fa(u)的期望startinf_time, 而u是fa(u)第i个递归进去的,那么考虑将剩下的k - 1个点放入对应的前i-1个位置,这样能对u的starting_time产生影响的概率:i1k1。那么总共的概率: ki1i1k×1k=12,而对应的权就是子树的大小。

C: Please

Problem:
有三个杯子,一开始钥匙在中间杯子里。然后,有若干次操作,每次可以随机选择两边的任何一个杯子和中间的杯子互换,求最后中间有钥匙的概率。操作数表示为n(<=10^5)个数的乘积,每个数(<=10^18),最后答案用分数表示,分母和分子都要对10^9+7取模。
Keyword:
动态规划、矩阵快速幂、数学、打表找规律
Analyse:
1.需要一个O(logn)的算法
2.如果不用分数,那么就可以直接用矩阵快速幂来做
Solution:
先不考虑分数表示的问题,用f(i,j)表示第i轮钥匙在j号杯子的概率,然后可以构造出一个3*3的矩阵来优化。把小数的矩阵化成分数矩阵,会发现因为数字太大矩阵直接存分数会超过long long范围。考虑把矩阵的前几个打表打出来观察中间的格子(只有它有用),发现一个规律:分母 =2m1 。分子分成两类,m为奇数的时候 = 2m113,m为偶数的时候 =2m1+13
然后可以理解为询问的是所有数乘积为幂数的结果,然后因为模数为质数,,所以幂数对phi(p)取模。然后分母为3的处理要用逆元。
Trick:幂数模后可能会为0,然后幂数-1为负数。所以当幂数为0时直接等于phi(p)。

D: Legen

Problem:
给出n个字符串,每个字符串有一定的价值,其中总长度不超过200个字符。然后给出l(<=10^14)个空格,每个空格可以填一个小写字母,形成一个句子。若从句子中读出一个字符串就可获得对应的价值,句子可以重叠读,即可用一段公共部分。
Keyword:
ac自动机,倍增思想
Analyse:
1.多个字符串且总长度给出,考虑使用ac自动机
2.l很大,考虑要用O(logl)的算法,如果l较小,完全可以直接动态规划
Solution:
如果l不大,可以建立ac自动机,然后设计状态f(i,j)表示第i位匹配到自动机上节点j的最大价值。但是,l很大,首先考虑的是矩阵快速幂,但是不知道如何维护最大值(其他pass的代码似乎都用了矩阵快速幂)。然后,拓展前面的状态定义,f(t,i,j)表示在用2^t步从自动机节点i走到节点j的最大匹配,这样就能在O(N^3)的时间内通过类似floyd的方式从t转移到t + 1。最后,把l转换成2进制,利用相同的方法得到答案。
Trick:
1.(1 << t)这种写法若存在超出int范围的危险,应在1后面加上ll。
2.在统计答案的过程中,应该多开一个数组来进行floyd的转移,避免存在已经利用了当前信息。

360

A: NP-Hard Problem

Problem:
一个图上给出n个点,m条边。要求你把点分成两个没有交集的集合,使得每条边的两个端点都处于不同的集合内。
Keyword:
二分图染色
Analyse:
1.若存在合法方案,那么就是把图分成了一个二分图
Solution:
因为有多个联通块,所以每个联通块都深搜一下,进行二分图染色。

B: Remainders Game

Problem:
假设已知一个数x模若干个数ci的余数,询问是否可以肯定x模k的余数。
Keyword:
数学、同余方程组
Solution:
我的想法一开始就是错的,讲一下看题解的内容和看完题解的想法。
如果假设是No,就会存在x1,x2,满足(x1 - x2) % ci = 0且(x1 - x2) % k != 0。然后,可得(x1 - x2) % lcm( ci ) = 0。分析一下,如果是No,则k不是lcm( ci )的约数。但是,能否证明k不是lcm( ci )的约数,结果就是No?后面就是自己的想法了,可以这样考虑,题目相当于给出了若干个同余方程组,设若干个数的最小公倍数cm,那么最后的解x肯定可以表示为cm * t + val, 只有当k为cm的约数时才能保证x模k一定的。
Trick:在处理lcm的时候是不能直接做的,可以转化为求k与所有ci的gcd的lcm,判断最后lcm是否为k。
Reflect: 思考问题的方向太片面,没有联系自己会的内容。

C:The Values You Can Make

Problem:
给出n个硬币和一种面值,有多种组成该面值的硬币方案,同时每种方案中你可以选出若干个硬币组成新币值。询问有几种不同的币值,并将所有的币值输出。
Keyword:
动态规划
Solution:
设计状态f(i,j,k)表示前i种硬币组成面值j的各种方案是否能组成新币值k。转移的时候注意一下边界,相对简单。
Reflect:
1.在分析数据范围后,要大胆地去从动态规划这个方向去思考问题。
2.设计状态要做到包含所有状态、同时要求简洁。

D:Dividing Kingdom II

Problem:
给出n个点,m条边,q次询问。每次询问,要求把l-r编号的边建成图,然后在新图上把点分成两个点集,若存在一条边两边的端点在同一集合答案就是这种边的最大值,否则答案为-1,现在要求最小的答案。
Keyword:
贪心、带权并查集
Analyse:
如果不是二分图,答案才不为-1
Solution:
正解的做法看不懂。此题是由于codeforces评测机太快,然后暴力过的。
暴力的做法:若图中只存在一个奇环,那答案就是奇环中的最小边。那么,对于所有的边从大到小排序,然后顺序加边,直到图中出现奇环。奇环可以用带权并查集来判断,并查集里每个节点带一个权值表示在二分图中它与它祖先的关系,更新的时候只需要更新祖先信息,因为子节点会在压缩路径的时候更新。

359

B:Kay and Snowflake

Problem:
给出一棵树,要求输出以每个点为根的子树的重心。
Keyword:
重心、搜索
Analyse:
若现在求以u为根的子树的重心v,而w是u的孩子中子树节点最多,那么v肯定在w的重心到v的路径上
Solution:
利用上面的分析,可以分开两次来搜索。第二次的时候用来找重心,重心另外一个定义:分成的所有子树大小均小于n/2。

D:Kay and Eternity

Problem:
在一个图上有若干个点,用一个k*k的矩形框点,问框住1-n个点的情况有几种。
Keyword:
扫描线
Analyse:
对于每个点考虑什么时候开始产生贡献
Solution:
一个点(x,y)在矩形的左上端点在(x - k + 1, y - k + 1)的时候产生贡献,同时可以知道什么时候没有贡献。将x坐标离散化,对每个点处理出两条线段,(l,r, y - k + 1,+1) , (l,r,y + 1,-1),然后从上到下扫描一遍,同时维护x坐标的信息以及更新答案。

358

A:Bear and Prime 100

Problem:
(交互题) 对方有一个hidden number, 你的程序需要每次输出一个数u,对方的程序会输出一个yes或no,表示u是否是hidden number。你的程序最多询问20次,然后必须做出回答hidden number是否为质数。
Keyword:
交互题、数学
Analyse:
考虑合数与质数性质
Solution:
从20次询问思考,分析一下只需要前15个质数就可以筛完除一个素数的若干次方的数。那么就考虑将前四个质数2,3,5,7的平方去处理,就可以筛掉一个素数的若干次方的数。

B:Bear and Twoer of Cubes

Problem:
给出一个范围[1,m],要求取一个值v。使得从v中不断挖掉一个最大的立方数,挖的次数最多,如果次数相同,要求v最大。
Keyword:
数学、搜索
Analyse:
1.对于两个范围[1,m1],[1,m2],若m1 > m2,则第一个范围取出的v肯定不比第二个范围的差
2.对于一个范围m,若a^3是小于等于m的最大立方数,则从中挖的方案中只有可能是a^3或(a - 1)^3
证明: 若此次挖a^3,则剩余[1,m - a^3]。若此次挖(a - 1) ^ 3, 则剩余[1, a^3 - 1 - (a - 1) ^3]。若此次挖(a - 2) ^ 3,则剩余[1,(a - 1) ^ 3 - 1 - (a - 2) ^3]。
根据性质1,可以发现挖的方案只需考虑前两种方案。
Solution:
根据分析的内容,可以对[1,m]向下搜索,每次分开两种情况,最差的目测是O(N/3* logN ),实际上是O(19*logN)。

D:Bear and Chase

Problem:
给出一个图,警察在图中捉贼。每天可以选择一个地方用一次探测器,探测器会显示贼的距离。共有两天时间,可以在第一天行动,如果失败就是结束。也可以选择等到第二天,而贼也会在原先的点到一个相邻的点。
Keyword:
概率、复杂度分析
Analyse:
1.若在原先位置的距离是a,过了一天距离为a-1或a+1或a。
Solution:
感觉官方解法很迷……
暴力枚举第一次选择的位置a、第二次选择的位置b、第一次的距离dis。然后,可以分析得枚举第一次距离和第二次距离的复杂度为O(3*n)。然后,对于奇怪的概率,直接暴力处理(还是不是很明白概率的处理)。

AIM Tech Round 3

B:Recover the String

Problem:
要求构造一个01串,使得该串的00子序列、01子序列、10子序列、11子序列刚好是规定的数量。
Keyword:
数学
Anaylse:
1.通过00和11的数量可以算出0和1的真实数量
Solution:
若设0的真实数量为T0,1的真实数量为T1,01子序列数量为A01,10子序列的数量为A10,则等式T0*T1=A10+A01成立。所以,只要满足放的方式使A10数量不错即可,最简单的构造方法就是把1全部放成一行往里面插入0。

C:Centroids

Problem:
给出一棵树,然后询问在第i个点做根的时候,可以移动一个点为根的子树并加在任意一个点下方,问第i个点是否能成为重心。
Keyword:
搜索、树
Anaylse:
1.分开两种考虑,每一个点需要考虑父亲方向的和自身重孩子方向的
2.每次考虑删去一个最大但是小于n/2的子树,这个需要在搜索中维护
Solution:
会发现搜索中,节点深度不断变大,需要考虑从父亲方向带来的影响。所以,每个节点都需要额外保存g(u)表示除了u的子树外所有节点到fa(u)能删去的最大子树大小,然后分开两边的考虑即可。还有一些细节,需要一些辅助的函数来计算。
Reflect:
1.一些状态的定义要清晰,不要把什么都混在一起。
2.在树上的处理,当要从父亲传递信息的时候,一般都要用到类似g函数的辅助。

D:Incorrect Flow

Problem:
给出一个网络流的图,每条边有流量上限、当前流量。但是,当前网络可能是错误的,可以调节每条边的流量上限、当前流量,每次操作代价都是1,询问改成合法网络的最小代价。
Keyword:
最小费用循环流
Anaylse:
1.若每条边的流量退为0,就是一个可行流。同时,用网络流算法跑出来的,也是可行流。
2.然后对于边分成两类讨论:上限大于当前、当前大于上限
Solution:
首先每条边假设退成0,记录需要的费用。
上限大于当前:在到当前流量前费用为-1,在两者间费用为+1,超过上界为+2
上限小于当前:在到当前上界前费用为-1,在两者间费用为0,超过上界为+1
观察发现,图中会存在负环和流量不平衡的情况,对此可以默认要求把-1的边先流光,然后把原图改成循环流,同时设置反向的边费用是1,表示可以可反悔。然后,就直接跑费用流。

352

A:Recycling Bottles

Problem:
有两个机器人分别在a、b两地,有一个垃圾桶在t地,然后给出若干个垃圾的坐标,可以使用一个或两个机器人去捡垃圾,但是每捡一个垃圾都要先放进垃圾桶再继续,询问两人走的总路程最短。
Keyword:
贪心
Anaylse:
1.可以发现除了第一次捡垃圾的过程,后面的都是从垃圾桶和垃圾之间来回,总距离一定。
Solution:
发现其实若不存在机器人就在垃圾桶,总和就是将所有的位置和垃圾桶位置的和的两倍。然后,考虑找出Scur - Snow最大的两个(或一个),然后减掉就是了。就是把那个东西排序一下。

B:Robin Hood

Problem:
给出n个数,k此操作。每次操作将最大数减1,最小数加1。当某一次操作完,原来的最大数小于原来的最小数,这次操作撤销并且结束操作,最后询问最大数与最小数的差。
Keyword:
二分
Anaylse:
1.减去的数和加上的数一定,即和是定值。
Solution:
根据上面分析的东西,其实可以写一个模拟,但是感觉很繁杂……
考虑二分一个最小值和一个最大值,每次判断的依据就是比最小值小的到最小值的差小于k,比最大值大的到最大值的差小于k。然而,这样子去处理可能会出现最大值小于最小的情况,解决方法是改变二分的上下界,最小值的上界是平均数,最大值的下界可能是平均数(或者+1,当不能是平均数时)。

D: Roads in Yusland

Problem:
给出一棵树,还有若干条直链及其费用,要求用一些直链覆盖整棵树上的路径,并要求费用最小。若不存在输出-1。
Keyword:
树形dp、线段树合并
Solution:
一种很经典的树形dp模型。
f[i]表示i的子树被完全覆盖,并且i与其父亲的边也被覆盖的最小费用。
转移的时候就是选中一条穿过i的链+剩余的孩子的f,还是很好理解的。
实现上可以用线段树合并,用链作为下标,对于每个点维护的就是i这条链作为被选中链的代价f[i]的值,维护一个最小值。每次转移,i所有的孩子的线段树要加上它所有兄弟的f,然后与i的那棵线段树合并。对于那些链,就是用vector打在对应点上。对于无解的情况,搜一遍就可以判断。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7211次
    • 积分:188
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    阅读排行