2023CYEZOI 线下比赛日记1

赛季将至,学校搭了 OJ,那么线下比赛开始了。

9/2 DAY 1

难度 NOIP–,但是很抽象,比如说有什么第一题看不懂,第三题暴力能过,第四题 O ( 3 n ) \mathcal{O(3^n)} O(3n) 剪枝搜索能过,但是 O ( n 2 log ⁡ n ) \mathcal{O(n^2 \log n)} O(n2logn) 的线段树只有二十分。
总之是我太蒻了。
赛时代码

T1 人类基因

TAG:模拟,位运算
赛时没看懂,导致只拿了九分(补交的不算啊)。
题目其实说的是:给 2 n 2n 2n 个数,其中存在的任意两个相同值可以组成一组,总共可以组成 n − 1 n-1 n1 组,但有两个数不能组成一组,输出那两个数。
空间只有 10MB,其实排个序就很好把相同的给去掉了,但是也有异或和做法,按二进制位统计,我写的是前者。
code

T2 Bribing Friends

TAG:背包,贪心
USACO 原题,直接放了洛谷链接。是一种动规思想的考察。
赛时想到既然 x i x_i xi 越小越划算,所以就按 x i x_i xi 升序排序,然后从前往后推,要选就尽可能用 x i x_i xi 降到最低价(除最后一个可以降的都降到零)。但是如果 x i x_i xi 状态转收益不具有最优子结构,不转还是超时。(遗憾的是,我赛时没有注意到前者的问题,以下给一个 hack)

5 3 50 
15 1 33
29 1 43
19 1 35
47 1 50
10 1 32

其实已经接近正解了。既然 x i x_i xi 只用于 i i i 的前几项, c i c_i ci 用于 i i i 的后几项,那么就进行前缀和后缀 d p dp dp,具体地, g ( i , j ) g(i,j) g(i,j) 表示 [ i , n ] [i,n] [i,n],花 j j j 的哞尼的最大受欢迎度, f ( i , j ) f(i,j) f(i,j) 表示 [ 1 , i ] [1,i] [1,i],花 j j j 的冰激凌甜筒的最大受欢迎度。整合答案时别忘了特别算一下中间部分优惠的一项。
code

T3 禅与园林艺术

TAG:抽屉原理,前缀和
思维题,赛时没想出来,打了暴力。
首先处理前缀和。发现本题特性模数 p p p 特别小,进一步通过抽屉原理想到:如果 r − l + 1 > p r-l+1 > p rl+1>p,那么必然存在 s u m i ′ = s u m j ′ ( m o d    p ) sum_{i'}=sum_{j'} (mod\;p) sumi=sumj(modp) 那么最小值就是 0 0 0。其他暴力很快求出。
code

T4 心理学概论

TAG:线段树
非常不错的题,唯独数据不合理,能卡掉 O ( n 2 log ⁡ n ) \mathcal{O(n^2 \log n)} O(n2logn) 的线段树,但是最优化剪枝暴力可以满分。赛时写的是 O ( n 2 log ⁡ n ) \mathcal{O(n^2 \log n)} O(n2logn) 的,但是统计答案不完全导致只有九分(为什么有wa但评测机就以tle一概而过以致我没第一时间意识到错误)。
其实我的算法也已经算半个正解了。首先按 a i a_i ai 排序,枚举 a i a_i ai,比当前 a i a_i ai 小的都选到 A A A,其余进入 B    o r    C B\;or\;C BorC。这里我就是建立以 b i b_i bi 为下标, c i c_i ci 为值的线段树,再枚举 b i b_i bi ,将 ∀    b j ≤ b i \forall\; b_j\leq b_i bjbi 放入 B B B,其余放入 C C C
这里第一步是合理的,枚举 b i b_i bi 处可以进一步优化。首先我们希望答案可以成为线段树的一部分,更新线段树也要在 O ( log ⁡ n ) \mathcal{O(\log n)} O(logn) 内实现。单调性是一个很好的性质,考虑到 m a x    c i = m a x j ∈ [ i , n ] c j max\;c_i = max_{j\in [i,n]}c_j maxci=maxj[i,n]cj 为后缀,而此后缀具有单调性,所以构造线段树,在 b i b_i bi 下标处存 m a x j ∈ [ i , n ] c j max_{j\in [i,n]}c_j maxj[i,n]cj r e s = b i + m a x j ∈ [ i + 1 , n ] c j res=b_i+max_{j\in [i+1,n]}c_j res=bi+maxj[i+1,n]cj,再存一个 b i b_i bi 方便运算。由于 m a x j ∈ [ i , n ] c j max_{j\in [i,n]}c_j maxj[i,n]cj 单调不升,故单次修改二分找到最后一个 x ≥ c i x\geq c_i xci,修改 [ x + 1 , b i − 1 ] [x+1,b_i-1] [x+1,bi1] c i c_i ci(显然,当 x x x 不存在,或 x > b i − 1 x>b_i-1 x>bi1 时不更新)。建议离散化,不建议动态开点线段树,因为后者对空下标不好处理。
code

总结

赛时期望得分: 100 + 100 + 20 + 20 = 240 100+100+20+20=240 100+100+20+20=240,实际得分 9 + 71 + 27 + 9 = 116 9+71+27+9=116 9+71+27+9=116。第一题理解题意有误,第二题写了假的,第三题暴力似乎挺快,第四题答案不完全统计。

9/6 DAY 2

合理的比赛,但第一题写炸。赛时码

T1 毒瘤计数题

TAG:组合数学
数学题,很简单推式子计算,但就是这样我也能写炸。
不多赘述,直接式子: ∑ i ∈ [ 1 , n − 1 ] 2 i − 1 ( 2 n − i − 1 ) = ( n − 1 ) 2 n − 1 + 1 − 2 n − 1 \sum_{i\in [1,n-1]}{2^{i-1}(2^{n-i}-1)}=(n-1)2^{n-1}+1-2^{n-1} i[1,n1]2i1(2ni1)=(n1)2n1+12n1 这不就是等比数列求和吗,但是赛时没看出来,算繁了,然后呢,中间用 n n n 代替 n − 1 n-1 n1,最后还没有换回来。而且,输出用快写没有 0 0 0 特判。导致痛失 90 90 90 分。
code

T2 普通图论题

TAG:树形dp
客观上,这题让我感受到了学校 oj 的神奇:同样的代码,两次提交,时间上可以差 20 % 20\% 20%,如下图:
做法树 d p dp dp。首先记录 u u u 节点子树中的最短距离,然后再通过 d p dp dp 推出非子树中的最短距离,其实后者如果站在父亲的位置就很容易看出来了,维护前者的最小和次小值就可以推出后者了。
有概率被卡常的 code

T3 简单数据结构题

TAG:线段树,构造
其实一开始想正解是完全没思路的,甚至我看到正解时都不敢相信。
从简单的开始分析:首先考虑一种 O ( q n ) \mathcal{O(qn)} O(qn) 的暴力,就是无脑地把所有区间在数轴上标出来,然后遍历互斥关系。接着,就是考虑到是静态二维问题,联想到惯用套路:二维数点。一对互斥关系可以看作两对平面上的点(正反两对),然后区间就是平面上 k 2 k^2 k2 个矩形,若矩形内有点则有互斥关系。举个例子: x , y x,y x,y 互斥,则在平面上记 ( x , y )    ( y , x ) (x,y)\;(y,x) (x,y)(y,x),然后 ∀ i , j ∈ [ 1 , k ] \forall i,j\in[1,k] i,j[1,k],矩形两个对顶点(大概是这样叫的?)为 ( q l i , q l j )    ( q r i , q r j ) (ql_i,ql_j)\;(qr_i,qr_j) (qli,qlj)(qri,qrj)。复杂度为 O ( ∑ k 2 log ⁡ n ) \mathcal{O(\sum{k^2}\log{n})} O(k2logn)
这两种解法仔细想想发现截然不同,尤其是复杂度上,差异很大,便可在此做文章。前者 O ( q n ) = O ( ∑ k k n ) \mathcal{O(qn)=O(\frac{\sum{k}}{k}n)} O(qn)=O(kkn) ,后者 O ( ∑ k 2 log ⁡ n ) = O ( k ∑ k log ⁡ n ) \mathcal{O(\sum{k^2}\log{n})=O(k\sum{k}\log{n})} O(k2logn)=O(kklogn) ∑ k k n + k ∑ k log ⁡ n ≥ 2 ∑ k ⋅ n log ⁡ n =    ⟺    k = n log ⁡ n \frac{\sum{k}}{k}n+k\sum{k}\log{n}\geq 2\sum{k}\cdot \sqrt{n\log{n}}\\ =\iff k=\sqrt{\frac{n}{\log{n}}} kkn+kklogn2knlogn =k=lognn 所以,原来单次询问中的 k k k 存在阈值,并可以采取不同策略(没想到暴力也是正解的一部分)。总复杂度似乎常数不大可以过,事实也是卡一下就可以。
实现要卡常不算简单,这里学了表示前缀和的线段树的构造方法,很有启发,详情见代码。
题外话,这题算不算毒瘤?
code

总结

赛时期望得分: 100 + ( 90 … 100 ) + 20 = ( 210 … 220 ) 100+(90\dots100)+20=(210\dots 220) 100+(90100)+20=(210220),实际得分 10 + 80 + 20 = 110 10+80+20=110 10+80+20=110。第一题算得不清楚而且答案 0 0 0 快写输出没有特判,第二题没有用链式前向星,并且实现方法常数太大(这个其实是预料之中,实在不敢确定改得对,而且事实证明,多试几次就可以顺利通过评测机xd)。第三题有点毒瘤

9/9 DAY 3

赛时码

T1 String Master

TAG:dp
终于,我拿满了第一题的分。挺简单的,纯的 d p dp dp,不多说了。(代码看上面赛时码)

T2 平均数

TAG:二分,归并排序
因为小数不足四位没有补零而暴力一分未得。感觉赛时二分分治都想过了,就是没想到怎么转化。
首先求第 k k k 小第一反应是分治,但是这个似乎想不通,只好进而考虑二分:二分平均数,求平均数比它小的区间有多少。然后 check 就不会写了。其实就是转化,遇到平均数想到可以算出每个数和平均数的偏离程度(就是差值),然后看有多少区间的和是负的,然后前缀和再逆序对。所以总复杂度为二分 + 求逆序对 = O ( n log ⁡ n log ⁡ a m a x ) \mathcal{O(n\log{n}\log{a_{max}})} O(nlognlogamax)
code

T3 Tourist Attractions

TAG:图论,bitset
bitset 复杂度为 O ( n w ) \mathcal{O(\frac{n}{w})} O(wn),所以用此存图。 a n s = ∑ ( d e g i − 1 ) ⋅ ( d e g j − 1 ) − ∣ S ∣ ans=\sum{(deg_i-1)\cdot(deg_j-1)-|S|} ans=(degi1)(degj1)S。其中 ∣ S ∣ |S| S 表示 i i i j j j 可以共同到达得点数。
code

T4 Walk

TAG:图论建模
难点一是建图。 ∃    E d g e ( i , j )    ⟺    v a l i    &    v a l j = v a l j \exist\;Edge(i,j)\iff val_i \;\&\; val_j=val_j Edge(i,j)vali&valj=valj,可以理解二进制下 v a l j val_j valj v a l i val_i vali 的子集。枚举每个权值向它的所有子集建边太复杂,考虑去简化。假如以每个权值为点,要满足子集关系,可以想到是向在二进制下仅一位的 1 1 1 改为 0 0 0 的点建边(如 0110 → 0100    o r    0110 → 0010 0110\to0100\;or\;0110\to0010 01100100or01100010),则一个点最多 20 20 20 条边,经过多条边即可满足关系。即过程为真实点层到虚拟点层再到真实点层,甚至如此多次重复。真实点出发的边权值为 1 1 1,从权值点出发的边权为 0 0 0。总边数 ∑ i ∈ [ 1 , 19 ] ( 20 − i ) ( 20 i ) ≈ 1 e 7 \sum_{i\in[1,19]}{(20-i){20\choose i}}\approx 1e7 i[1,19](20i)(i20)1e7
难点二是虚拟建边然后跑 O ( m ) \mathcal{O(m)} O(m) 的搜索。虚拟建边二进制随便搞搞(如 lowbit)就能在过程中 O ( 1 ) \mathcal{O(1)} O(1) 推出。搜索因为权值为 0    o r    1 0\;or\;1 0or1,所以可以按照 dijkstra 的思路用 deque 优化(因为 priority_queue 的复杂度大)。
这样一看其实代码不难,重在思维。
code

总结

赛时期望得分: 100 + 40 + 70 + 40 = 250 100+40+70+40=250 100+40+70+40=250,实际得分 100 + 0 + 0 + 40 = 140 100+0+0+40=140 100+0+0+40=140。第二题输出去小数末尾 0 评测机不算对,第三题写了假(思维古怪)。感觉偏简单题都没搞出来,挺可惜的。

9/17 Day 4

最近有点生病,而且题目都不难,故不写题解了。赛时码+订正码

标签:搜索,kmp,dp,图论建模,最短路

总结

期望得分: 80 + 30 + 100 = 210 80+30+100=210 80+30+100=210。实际得分: 100 + 27 + 69 = 196 100+27+69=196 100+27+69=196。第一题似乎读入量大,而导致本地可以构造超时数据,但评测机似乎给过了。第二题分差应该是分值分布不均。第三题数组开小了。由于第二题涉及 kmp,故场上没写出正解,赛后学习 kmp。

9/20 Day 5

或许算是比较难的比赛?无赛时码。

T1 堆

标签:dp,剪枝,分块打表

数据 1 0 9 10^9 109 的规模首先想到推结论,然而这题却是完完全全的 d p dp dp,使用 O ( n 1000 log ⁡ n ) \mathcal{O(\frac{n}{1000}\log n)} O(1000nlogn) 的算法通过。 f ( x ) f(x) f(x) 表示 x x x 个元素的二叉堆的方案数,得到转移 f ( x ) = f ( L ) ⋅ f ( R ) ⋅ ( n − 1 L ) f(x)=f(L)\cdot f(R)\cdot {n-1\choose L} f(x)=f(L)f(R)(Ln1) L , R L,R L,R 分别表示左右子树的节点数)。不是很直观,但是可以参考解决全排列大小关系的思路,如 At_dp_t Permutation,大小关系是相对的,然后就可以理解转移方程了。直接转移可以得到 O ( n ) \mathcal{O(n)} O(n) 的算法,可以 60 p t s 60pts 60pts

继续优化:一、因为每一个完全二叉树根的两个子树至少一个是满二叉树,所以可以预处理满二叉树,时间上为 O ( log ⁡ n ) \mathcal{O(\log n)} O(logn),但想通过 1 0 9 10^9 109 的规模在空间上仍不可。二、优化阶乘打表,就是隔开大概 1 0 6 10^6 106 个数(隔得少代码太长)打表,时间上变为 O ( n 1000 log ⁡ n ) \mathcal{O(\frac{n}{1000}\log n)} O(1000nlogn) 可过。

code+generator

T2 密文

标签:构造,图论建模,mst,位运算,trie

询问为 p r e r ⊕ p r e l − 1 pre_r\oplus pre_{l-1} prerprel1 p r e 0 = 0 pre_0=0 pre0=0 已知,希望知道 ∀ p r e i , i ∈ [ 0 , n ] \forall pre_i,i\in[0,n] prei,i[0,n]。抽象为 通过如何方式知道若干条 p r e x ⊕ p r e y pre_x\oplus pre_y prexprey,可以通过 p r e 0 pre_0 pre0 求出 p r e i , i ∈ [ 0 , n ] pre_i,i\in[0,n] prei,i[0,n],其中若将 p r e x ⊕ p r e y pre_x\oplus pre_y prexprey 视为 x ↔ y x\leftrightarrow y xy 的边,知道一个端点就能知道另一个,故转化为最小生成树,模板 Xor-MST。实现为构造 trie,树上左右儿子皆有的点    ⟺    \iff 两个点的 lca,故对于这些点,求 m i n i ∈ l s , j ∈ r s p r e i ⊕ p r e j min_{i\in ls,j\in rs}{pre_i\oplus pre_j} minils,jrspreiprej,而字典树中叶子节点表示的数从左至右有单调性,故枚举一个子树,然后到另一个子树匹配异或最小的数。复杂度 O ( n log ⁡ n log ⁡ a i ) \mathcal{O(n\log n\log a_i)} O(nlognlogai),可过。

code

T3 树

标签:树哈希,树的重心,dp

9/23 Day 6

小丑比赛。赛时码+订正码

T1 brick

标签:dp

很好想的 d p dp dp,但是有一些细节。 f ( i , j , k ) f(i,j,k) f(i,j,k) 表示 i i i j j j 行用了 k k k 发子弹的最大收益。可以推到 f ( i , j + 1 , k + 1 ) f(i,j+1,k+1) f(i,j+1,k+1) f ( i + 1 , n , k ) f(i+1,n,k) f(i+1,n,k)。但是可能打完后剩一发,所以希望遇到可以最后打的砖块后将有奖励的砖块的要求从 k ′ < k k'<k k<k 变为 k ′ ≤ k k'\leq k kk,故再记一位,表示是否遇到可以最后打的砖块(即打完无奖励,直接换到下一列),但要注意不能一次都不打就转到上述第二位,我就是这里没有初始化错的。

赛时期望得分 100 100 100,实际 40 40 40

T2 math

标签:数学,递推

很简单的想法,略复杂的运算。推式子: f ( i ) = a i + b i + c i ,    g ( i ) = a b i + a c i + b a i + b c i + c a i + c b i f(i)=a^i+b^i+c^i,\;g(i)=ab^i+ac^i+ba^i+bc^i+ca^i+cb^i f(i)=ai+bi+ci,g(i)=abi+aci+bai+bci+cai+cbi,则有 a b c = f 3 ( 1 ) − f ( 3 ) − 3 ∗ g ( 2 ) 6 abc=\frac{f^3(1)-f(3)-3*g(2)}{6} abc=6f3(1)f(3)3g(2),然后 f ( i ) = f ( 1 ) f ( n − 1 ) − g ( i − 1 ) ,    g ( i − 1 ) = f ( i − 2 ) ⋅ g ( 1 ) 2 − a b c ⋅ f ( i − 3 ) f(i)=f(1)f(n-1)-g(i-1),\;g(i-1)=f(i-2)\cdot\frac{g(1)}{2}-abc\cdot f(i-3) f(i)=f(1)f(n1)g(i1),g(i1)=f(i2)2g(1)abcf(i3)

赛时期望得分 100 100 100,实际得分 40 40 40。原因:operator 在结构体中直接引用自己的内容会修改其值。

T3 xor

标签:trie,位运算

很简单的 T3, l o w b i t ( x ⊕ y ) lowbit(x\oplus y) lowbit(xy),即 x , y x,y x,y 二进制下最小的不同位,考虑二进制构建 trie,这样可以一层层枚举当前位为最小的不同位,类似线段树的统计。

赛时期望得分 100 100 100,实际得分 40 40 40,原因:常数太大,导致有概率被评测机卡了,比如赛时 1002ms,赛后 893ms,然后 subtask 又是捆绑的,故得分低,好气哟!!!!!

下文

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值