20190812B组
T1:100(0)
赛时:
这道题想到正解应该不难,只不过比例的地方要小心。
并且,要注意这题序列长度不超过10^9,所以要用long long
赛后:
贪心的思想,不难发现,如果序列前 i 个方块 B 和 W 的比例和 B 和 W 在整个序列中的比例相同。
我们一定会把第 i 个方块与第 i+1 个方块分开来得到尽量多的分段数。
比较暴力的做法就是把序列打开,对于序列的每个位置 i 统计 1~i 中 B 和 W 的数量,时间复杂度是 O(L),其中 L 表示序列长度。
100%,我们可以先算出 B 和 W 在整个序列中的比例,再 O(n) 扫一遍,对于每次加入的方块,判断一下是否存在会出现目前加入的 B 和 W 的比例与整个序列相同,有就将 Ans+1 即可。 注意考虑整个序列都是 B 或者都是 W 的情况。
算法:
贪心
T2:0(40)
赛时:
这题乍眼看去相似一道简单的贪心题。
可是,本想水个40分,可谁知一分都未水到。
赛后:
首先来想最简单的动态规划,通过第一个数的限制,我们可以得到每个位置的状态可以从哪 些位置转移过来,得到如下形式的式子: f(i) = ????=?[?] ?−1 (?[? + 1][?] + ?[?]) 其中 s[i][j]表示从 i 到 j 的最大值,l[i]表示 i 位置最多向左走到哪里。 然后套路一波,用个单调递减的单调队列,每次将队头不合法的依次踢掉,然后我们来想想, 这样我们只是得到了可以转移过来的状态集,那么如何维护答案呢?
观察下图:
现在我们的 i 在位置 8 上,红色框表示 i 向左最多到达的位置(即 2 与 8 的 p[i]是一样的) 可以看出,除了队头之外,其他的在单调队列里的元素的贡献都是从前面一个位置的 f 转移 而来的(因为 f 是单调不减的),而队头的则是依赖于 l[i]的。
假设当前的队列为:a[head. .tail]且∀head ≤ i < tail, a[i] < a[i + 1] 那么当前点的答案为:max(????=ℎ???+1 ???? (ℎ[?[?]] + ?[?[? − 1]]) , h[a[head]] + f[l[i] − 1]) 观察到每次我们移动一个点是有许多没有变的状态的,每个元素进一次出一次,于是我们用 堆或者其他数据结构来维护队列中每个元素的贡献,对于队头特殊处理。
时间复杂度O(n ???2n)
算法:
dp&单调队列
T3:0(0)
赛时:
这一道题看不懂呀!!!
那赛时就更不用说用什么思路了。
不过看懂也不知如何下手。
赛后:
算法:
三分
T4:0(0)
赛时:
一看就知到是一道最短路。
可是有思路但实现起来太复杂了。
于是打到一半,因前面调试第一题太久,突然听到一声巨响——
比赛结束了~~~
赛后:
本题有两个部分:
(1)一串0和1组成序列,限制条件[a,b,c],表示第a个数到第b个数之间最少有c个1。
设s[i]表示前i位中1的个数。
对每个条件[a,b,c],有s[b]-s[a-1]>=c,即s[a-1]-s[b]<=-c
注意隐蔽条件:
s[i]-s[i-1]>=0,即s[i-1]-s[i]<=0
s[i]-s[i-1]<=1
用SPFA求出s[],s[i]-s[i-1]就是第i个数的属性。
(2)有n个结点,从x直接飞到y,当且仅当存在一条x→t[0]→t[1]→…→t[k]→y的路径:
dis[x→t[]→y] <= L,并且t[]的属性为0
最多飞K次(此时路径长度按0算)
问从1到N的最短路;
dp[u,t]表示从1出发到u点飞t次的最短路
初始条件:dp[1,0]=0;
状态转移:使用spfa求解
for(u=1;u<=N;u++){
if(dp[u][t]>dp[u][t]+g[u][v])dp[v][t]=dp[u][t]+g[u][v];
if(t<K&&g[u][v]<=L&&dp[v][t+1]>dp[u][t])dp[v][t+1]=dp[u][t];
}
算法:
最短路&dp