edu152

edu 152

总评:这次的 \(A\)\(B\) 都是水题,感觉不如上次的题难,\(D\) 没时间做了,实际上让我做我也不一定能做出了/kk,只能说是做少了,但是听 psq 说 E 和 F 才适合中国宝宝的体质,那我前面的几个题就题解简化一下

A

因为上下比如有面包,所以用面包能叠出来的层数和馅料叠出来的层数取 \(min\) 即可

Code

B

发现只有 \(a[i]\) 减到 \(<=k\) 的时候才能一次减掉,所以直接让 \(a[i]\%k\) ,如果为 \(0\) ,那么加 \(k\) (因为是不会先减去等于 \(k\) 的)

从大到小排个序,输出答案即可

Code

没有 1A 原因:忘记判断 \(a[i]\%k==0\)

C

上来就想偏了,想了接近 40 min 才会,真是菜死了

假如串为 \(011011\) ,那么排完序变成 \(001111\) 也就是说只排序了 \(2,4\) ,感性理解也就是排在前面的 \(0\) 都不需要排序,后面的 \(1\) 都不需要排序

那么对于 \(l\)\(r\) ,也就是找到 \(l\) 后的第一个 \(1\) ,和 \(r\) 前的第一个 \(0\) ,如果 \(l>r\) 也就是说不用排序,全都改成 \(0\) 就来记录就好了

那么我们直接用 \(l\)\(r\) 来记录一个串在 \(l,r\) 排序过了

但是 \(vis[N][N]\) 会炸掉,所以搞个 \(hash\) 来做就好了

Code

没有 1A 的原因:不用排序的判定落了

D

dp做法:

\(dp[i][j]\) 表示前 \(i\) 个数填完,第 \(i\) 位的剩余数字为 \(j\) 的最小贡献

\[dp[i][a[i]]=\min(dp[i-1][0]+1,dp[i-1][1],dp[i-1][2]) \]

但是如果 \(a[i]\) 不等于 \(0\) ,那么可以从这一位开始向前或者向后全是正数的连续段变成红色

\[dp[i][a[i]]=min(dp[pre[i]-1][0],dp[pre[i]-1][1],dp[pre[i]-1][2])+1 \]

\(pre[i]\) 表示以 \(i\) 为下标,连续段能到达的左边第一个 \(0\) 的位置

假如现在有一个连续区间 \(1,2,...0...1,2\) 那么从最前面向后面染,和从后面像前面染,是一样的,因为每一个数都需要减去 \(1\) ,而且最后的贡献都是 \(1\) ,所以是等价的

Code

贪心做法:

发现 \(2\) 可以把一个连续段并且两边的 \(0\) 的染红,\(1\) 可以把一个连续段和一段的 \(0\) 染红,\(0\) 的只能染自己

并且这三个的贡献都是 \(1\) ,所以贪心很明显

先做 \(2\) 的,再做 \(1\) 的,最后做 \(0\)

\(2\)\(0\) 直接扫一遍就好了,但是 \(1\) 选择的方向怎么办呢?

因为我们是从左到右枚举,所以选择的 \(0\) 在左端,如果左边的 \(0\) 已经被覆盖过了,那么选右边,可以发现这样一定可以覆盖最多的 \(0\) ,不存在浪费的行为

Code

没有赛时做出来,上来想的 \(dp\) ,没想到 \(2\) 的转移是这样的,所以没列出来转移方程

E

1.线段树

如果在数组最右端加入一个下标为 \(i\) 的数,以 \(i\) 为右端点,可以找到多少个左端点使得满足条件

\(lmx\) 为当前点的左边第一个大于他的数的下标,\(lmn\) 为当前点左边的第一个小于他的数

两种可能:

  1. 那么 \(lmx+1\)\(i\) 都是 \(<\) 当前数的,所以从 \(lmx+1\)\(i\) 都可以作为右端点的左端点

  2. 但是 \(lmn+1\)\(i\) 都是 \(>\) 当前数的,所以从 \(lmn+1\)\(i\) 都是不可以作为左端点的

这两个必然有一个等于 \(i-1\) ,所以说选择其中一个即可

但是还有一种可能,比如 $1\ 5\ 2\ 3\ 4 $ ,以 \(4\) 为结尾,\(2\ 3\) 都是可以作为左端点的,但其实 \(1\) 也可以作为左端点,发现在 \(5\) 时,他还作为 \(5\) 的左端点被统计一次,也就是说新加进来的数,不会影响到原先数的最大值,原先可以作为左端点的还是不用动,但是如果左端点符合第二个可能,那么就不能作为左端点了

Code

没有 1A 的原因:忘记是覆盖了,而且 \(tag\) 可以是 \(0\) ,所以判断需不需要传递下去要用 \(-1\)

2.钦定一个点为最大值

设当前点为区间的最大值,假如他的下标为 \(x\)\(lmx\) 为当前点的左边第一个大于他的数的下标,\(lmn\) 为当前点左边的第一个小于他的数,\(rmx\) 为当前点的右边边第一个大于他的数的下标,\(rmn\) 为当前点右边的第一个小于他的数

\(l>=lmx+1,r<=rmx-1,l<=r\) 时,这个点为最大值,那么现在需要找到其实就是区间最小值的小标在最大值左边的区间个数

  1. 枚举左端点的下标 \(ll\),找到当前 \(ll\)\(x\) 的最小值 ,然后取 \(pos\)\(rmn-1\) ,这个时候从 \(x\)\(pos\) 作为右端点,\(l\) 为左端点的区间都是符合的,如果 \(pos>r\) 的话,说明右边没有比左边更小的数,也就是有整个右边都可以为可行区间,和原先的 \(x\)\(pos\) 的贡献取 \(min\) 即可,可以发现 \(rmn\) 一定在 \(x\) 之后,不如最小值就会变成 \(rmn\) 这个数
  2. 枚举右端点的下标 \(rr\),找到 \(x\)\(rr\) 的最小值,发现需要在左边找到一个比右边更小的数,也就是 \(lmn\) ,那么从 \(l\)\(lmn\) 都可以作为左端点,右端点为 \(r\) 的区间都可以为合法区间,并且 \(lmn <x\) 证明同上,但是可能 \(lmn\)\(l\) 还小,那么这个时候没有贡献,直接和 \(0\)\(\max\) 即可

这里我们先钦定 \(x\) 不能为右端点,最后直接加上 \(x\) 为右端点的答案

这里的原因为枚举 \(x\) 为右端点,在 \(2\) 中是无法统计答案的,所以直接最后加就是了

发现 \(1\)\(2\) 两种一个是枚举左端点,一个是枚举右端点,两种的答案其实是一样的,但是我们想要降低复杂度就要找枚举次数更少的一边

posted @ 2023-09-01 10:48  taozhiming  阅读(8)  评论(0编辑  收藏  举报