近期口嗨题解-专栏

前言

由于现在平时补题的时间不太多,可能看懂一个题解半小时,

然而,有时手头有别的事,就忘了实际ac&写博客,就这么把一个题咕掉了,

对于自己现在的水平来说,想出怎么做(思维难度)比怎么实现ac更重要,然而后者更耗时

所以打算开一个口嗨专栏,像是补一个题的过渡态,

把看懂题解的题先简写在这里,后续无论是否补上,也可以有一个回顾的地方

近期题目集锦

Codeforces Round #808 (Div. 1)

这场长沙一中出的cf,质量还是很高的

A. Doremy's IQ(贪心)

n(n<=1e5)场比赛,第i天难度ai(1<=ai<=1e9),你的初始智商是q(1<=q<=1e9)

如果你当前智商>0则有权参加比赛,每天你都可以选择是否参加比赛,

1. 如果不参加,什么都没发生

2. 如果参加,且ai>q,则当前智商q减1,ai<=q则什么都不发生

要求参加比赛数最大,输出这n天你的选择的01串

做法1:如果q>=n显然全取,否则最终智商一定为0,而{第i天减1,后面提前减为0,导致最后的有一些不选}显然是不如{把第i天减1的机会往后挪,这样有可能能有更多的可以选},所以,可以二分天数x,从x天开始每天都选。

做法2:如果q>=n显然全取,否则最终智商一定为0,显然降的机会发生在后面是更优的。逆序看待这个过程,把顺序的降认为是逆序的升,顺序的不操作认为是逆序的不操作,就可以直接贪心了,因为这样天数越小智商越高。

B. Difference Array(性质题-暴力)

长为n(n<=1e5)的不降序列,第i个值为ai,构造新数组b,b_{i}=a_{i}-a_{i-1}

将b数组排序后,记为新的a数组,可以发现a的长度减1,重复这个过程,直至a只剩一个元素

求最终a这个元素是几,特别地,\sum a_{i}\leq 5e5

做法1:由于差分数组的元素种类数是根号级别的(考虑斐波那契数列),所以,可以用map暴力地维护,当前(key,value)表示元素key的值有几个。key值域上相邻会新增一个差分元素,相同元素做差分,只会新增0元素。

做法2:暴力排序,只对非0元素那一段排降序,排序时最多排入一个0,一样的效果。

复杂度证明:

C. DFS Trees(性质题-树上差分)

n(n<=1e5)个点,m(m<=2e5)条边的无向图,第i条边的边权是i,

对于每个点,执行给出的函数findMST(i),能得出最小生成树边集的输出1,否则输出0,

vis := an array of length n
s := a set of edges

function dfs(u):
    vis[u] := true
    iterate through each edge (u, v) in the order from smallest to largest edge weight
        if vis[v] = false
            add edge (u, v) into the set (s)
            dfs(v)

function findMST(u):
    reset all elements of (vis) to false
    reset the edge set (s) to empty
    dfs(u)
    return the edge set (s)

输出最终的长度为n的串

做法:由于边权互不相同,所以MST唯一,考虑先构建出MST。

结论:若dfs过程中不存在横叉边,则这样找出的就是MST。

此题用在无向图这里,是个很好的性质题了。

Tarjan 复习 - poozhai - 博客园

树边:想保留的边。

前向边:又搜到儿子了。

返祖边:又搜到父亲了。

横叉边:又搜到兄弟了。

考虑官方题解给出的图:

根据MST性质,u-v不被取,说明u-v是这个环上权值最大的边,

如果从t/u/o/v开始搜,u-v都是返祖边,不被取;

而从a/b/c/d/e/f开始搜,u-v都是先被搜到的边,导致环上其他边成为横叉边,不符合题意

这表明,对于非MST上每条边(u,v)来说,只有两种情况符合题意:

1. 当v为根时,u这棵子树

2. 当u为根,v这棵子树

其他点都不符合题意,需要打个差分标记:

1. 若u和v是祖先关系,需要对u到v这一条链及这条链旁边的所有点标记

2. 若u和v不是祖先关系,需要对非u子树、非v子树以外的所有点标记

	for(int i=1;i<=tp;++i){
		int u=es[i].v,v=es[i].nt;
		if(dp[u]>dp[v])u^=v^=u^=v;
		int w=lca(u,v);
		if(u==w){
			--vis[v];
			++vis[jump(v,dp[v]-dp[u]-1)];
		}
		else{
			++vis[root];
			--vis[u];
			--vis[v];
		}
	}

题解打的是子树加标记,还是挺好写的

AtCoder Beginner Contest 259

Ex. Yet Another Path Counting(暴力)

n(n<=400)行n列的二维矩阵,第i行第j列有一个数字aij(1<=aij<=n*n),

你可以从某个格子出发,每次只能向下走一格或向右走一格,

求起点和终点数字相同的方案数,答案对998244353取模

做法:优雅的暴力

做法1:枚举相同数字对(x1,y1)和(x2,y2),然后用组合数算(类似卡特兰数,x步里选y步用于向右),点对数平方为O(n^4)

做法2:直接dp,dp[i][j]表示起点在(i,j)及左方/上方,当前走到(i,j)的方案数,枚举颜色,每次只对有这种颜色的标1,其他颜色标0,最后统计方案数总和,颜色最坏为n^2级别,每次遍历n^2,,为O(n^4)

考虑优雅的暴力,同颜色数>n时用做法2,<=n时用做法1,就降到了O(n^3),确实很妙

AtCoder Beginner Contest 258

Ex. Odd Steps(矩阵快速幂优化dp)

求满足以下条件的序列X的方案数,答案对998244353取模:

1. 序列X里每个元素都是奇数

2. 序列X元素之和恰为给定的S

3. 给定n个数a1,...,an,X的前缀和序列中不能出现这n个数里面出现过的数

题目满足n<=1e5,1<=a1<...<an<S<=1e18

做法:矩阵快速幂优化dp

考虑前缀和序列Y唯一映射出一个序列X,考虑朴素的前缀和序列的dp转移,

dp[i]=dp[i-1]+dp[i-3]+dp[i-5]+...,由于dp[i-2]=dp[i-3]+dp[i-5]+...,,所以dp[i]=dp[i-1]+dp[i-2],

考虑矩阵快速幂维护这个值,但是中间有一些值是要ban掉的,此时dp[i]为0,并不符合该式子,

如果dp[i]被ban了,手动搞出dp[i+1]和dp[i+2]之后继续转移,感觉比较难写(如果dp[i+1]也被ban了呢)

所以,考虑用dp值和前缀和sum两个值,来维护矩阵快速幂转移,

这样即使当前dp值为0,sum也能继续转移,每次对两个相邻元素ai和ai+1用矩阵快速幂

复杂度O(k^3*n*log1e18),k取2或3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值