codeforces C题若干只[round1]

来源:互联网 发布:软件功能结构图 编辑:程序博客网 时间:2024/05/21 09:19

最近做题缺少好的思路,听说codeforces聚集了各种神奇的想法(神奇的暴力233),

于是从中等难度的c题入手,以学习为主,实在不会了就看题解了,理清思路和为什么要这么想的就好,不贴代码


codeforcesd 455c

给一个无向图,有两种操作,

1.给一个点x问x所在的联通分量里的最长路

2.合并x。y两点所在的联通分量,使得新联通分量的最长路最短


并查集+一个小的dp维护最长路值

合并后,取两个集合中较大的一个最长路值,和(两个各取一半+连接的1)比较,取大值

bfs两遍,找到联通分量中的最长路(边权都为1的dij)

用set维护联通分量数目


453c

给定一个无向图

任选一个起点,使得访问每个点的次数奇偶与最后一行的输入一致

dfs这个图,对于dfs树,优先保证其子节点的访问次数与要求相同,再通过一次根与非其子节点的操作调整根节点

过程中一旦遇到无法调整的状态(一定发生在整棵bfs树的根节点),就输出-1


449c

在1到n中最多能取出多少对数,使得每对数的gcd都大于1

我的想法,就是在筛素数的过程中,每找到一个素数,就按顺序把它的倍数两两凑成一对,如果最后恰好剩下一个,就留着,给以后的素数的倍数配对用

想了好久都觉得对,不过,后来举出反例了,比如n=34,如果按我的方法,13和17的倍数26和34都在2的一轮中被用来配对了,造成13和17浪费了

怎么避免这种现象呢,就应该用最小的素数2的倍数来补全(2的倍数最多,最容易找),如果一个数k的倍数还剩下奇数个没有配对,就把一个是2的倍数的扔下,其余的两两配对,这样就能很好的利用奇数个中剩下的那个数了

觉得这种题好难一次全想对。。


448c

有一些宽度为1,高度为a[i]的木板横向排成一排,每次可以粉刷宽度为1的任意长度的横或竖条,问最少刷几次能把这些木板全部刷满

考虑横向连续的木板越多,横着刷的优势越大,否则,如果刷到顶部了,就全都竖着刷比较好

问题就是找到这些横着刷和竖着刷的分界线,上面都竖着刷,下面都横着刷

而横着刷的最多条数是由最低的那个木板决定的

所以,递归最低的板两边的部分即可

在区间(l,r)上,找出a[i]的值最小的点,然后取return min(r-l+1,dfs(l,m-1,a[m])+dfs(m+1,r,a[m])+a[m]-k);前者为全都竖着刷,后者是横着刷然后递归

dfs()的第三个参数为当前的高度


446c

线段树,

q1是给l到r依次加上fib的前l-r+1项

q2是查询和

线段树维护多个域,第一个域一定是和

定义其他域时,要满足叠加和可以拆分的性质

如果以选择的是fib的第几项为另一个域,则满足可拆分性,不满足叠加性(fib的第x项和第y项相加不等于第x+y项)

若以该段fib的第一项和第二项为另两个域(作为懒标记下传),就可以了,只是拆分的时候复杂度稍高


445c

给一个图,点和边都有权值,求密度最大的子图,密度为点权和除以边权和

想了好久好久,怎么来dp全图着求,然后怎么也找不到dfs的顺序使它无后效性。。。。。。。

看了眼题解。。发现直接枚举每条边求出最大密度的一条就好了。。简直蛋碎一地啊。。。

可以证明,但是,直观想象一下,一个图里的不同边密度肯定不同,而整个图的密度是接近平均值的,所以密度最大的一条边的密度一定大于这个图的平均密度。。。。

(看来不要见到这种求最优的题就想是不是一种没见过的dp。。。


444c

修改类的线段树

把一个区间的值都修改为x,同时在sum的对应位置加上这个新x与旧x的差的绝对值

这类问题要求把一个区间改成某个东西,而不是加上某个东西

这种线段树的懒标记只在一层上,不是从根到这一层的每层都有的

但是,这题在找到对应区间标上懒标记以后,还要继续向下找到原来的懒标记,并更新成sum,回溯

(如果原来的懒标记离根更近,就向下push

由于delta可以直接通过新和旧的x,以及区间长求出来,所以不用再加新的辅助域了

(这种修改型的懒标记和增加型的还是有所不同的)


443c

有5种花色的牌,每种花色都有1到5几张牌

知道牌的个数,但是不知道位置

有一种操作,可以显示一种数字或一种花色的牌的位置,问至少这样操作几次,能找出所有牌的位置

开始想的是颜色数-1 + 数字个数-1 直接算出来,但是被样例2举出反例了

这是道很nb的爆枚,一共有十种操作,我们爆枚每种操作取还是不取,对每种情况,通过判断题里给的牌是否有两张一样的对应的识别序列一致,如果有,则不能通过这样的识别序列唯一确定位置!

学两个姿势,

第一个,for(int i=0;i<(1<<n);i++)爆枚每种情况

第二个,vector和set都有==操作!!!,vector相等要数和位置都相等,set只要数等就可以!和传统意义上的集合一样!!

(大呼一声,叼叼叼!)



0 0
原创粉丝点击