2025做题

01-18

居然到18号才开始写日记/qd/qd

  • 道路の建設案
    曼哈顿距离不好做,考虑转换成切比雪夫距离,然后就把绑定的两维的限制变成两个一维的限制了,然后二分答案,对于每个二分的答案x,都把当前遍历到的值到\(x_i-x\)都放到set里,然后对于y这一维直接在x里查就行了,如果有的话那res就加一,最后看看有没有达到限制就行了。转换挺巧妙的。
  • k-d-sequence
    我看题解才会的。首先先把序列都对d取模,那么合法的就一定是连续一段一样的值,然后考虑对一段模完一样的值都变成模d的余数,那显然合法的就是这里的一段排序之后max-min+1-(l-r+1)<=k,然后转换一下就变成了max(L,R)−min(L,R)+L≤k+R,考虑枚举r,然后发现这玩意可以用线段树维护一下,具体地,肯定是这个数的余数大于前面的数的话那这个数就要进线段树更新,然后发现这玩意不好直接维护,用一个单调栈就好了,难想又难写。
  • Pudding Monsters
    考虑每行每列只有一个布丁,所以我们直接按x轴压成一维,然后就是上一题了。
  • 上帝造题的七分钟 2 / 花神游历各国
    胡扯题,发现\(10^6\)开6次根号就到1了,所以可以把全是1的区间打个标记,如果要修改的区间全是1的话就不用改了,然后用改的直接暴力改,反正用不了多少时间,然后就是普通线段树了。

01-20

  • Blocking Elements
    注意到复杂度,只能\(O(nlogn)\),所以考虑二分,二分答案,然后发现可以用第二条作为限制,只要这一段的和大于二分的答案了就把这个点变成分界点,最后判断分界点的和是否合法,但是显然这样很假,甚至过不了第二个样例,因为第二个样例是把第一个变成分界点,然后就遇到困难了,发现不知道在哪开始作为第一个分界点的时候答案是最优的,所以就想到可以dp,把每一个点是分界点的情况都算一下,具体地,设\(f_i\)表示第i个选成分界点的最小价值,转移就是在\(i-1\)到尽量靠前的满足这一段的和小于二分的答案,在这一段里找到上一个分界点,使值最小。然后发现这样dp复杂度是\(O(n^2)\)的,但是发现那个上一个的最小的分界点的那段可以做dp的时候用单调队列维护,所以dp就愉快的变成\(O(n)\)的了,总复杂度是\(O(nlogn)\)
  • Magic Matrix
    注意到数据范围很小,前两个限制可以暴力做,后面一个发现很难做,但是发现如果一直把限制递归下去,发现其实就是在一个图上的任意一个环上的任意一条边都满足这条边以外的环上的其他边的最大值比他大(这玩意能想出来的都是神人了),然后就发现如果对于边排序,只要当前遍历到的这条边不在环里就是合法的,反之就不合法,然后就做完了,复杂度可以近似估算为\(O(n^2logn^2)\)
  • Mind Control
    一眼题,没什么写的必要。
  • Flowerpot S
    考虑二分答案,然后发现是\(O(n^2logn)\)的,过不去,考虑优化,发现可以提前用单调队列处理出来二分的答案的长度里的最大值和最小值,然后直接\(O(n)\)扫一遍判断合法不合法就行了
  • 萌萌哒
    神人题,发现很容易有一个并查集的暴力,就是对于每个限制区间暴力并查集合并,然后最后直接看有几个不同区间就行了,但是要\(O(n^2)\),然后就不会了,但是感觉已经到头了,应该得数据结构优化,但是想了很久也只能想到线段树,但是不会怎么线段树+并查集,所以就不会了,看了题解之后才知道原来可以用倍增,然后局势就豁然开朗了,直接对于限制下放到下面两个区间,然后最后统计答案就行了。
  • XOR Tree
    这种树上异或的玩意显然第一眼就能想到转换成到根的路径,然后就有一个很显然的\(O(n^2logn)\)暴力,具体地,枚举lca,然后对于子树内如果有两个点的异或再异或上lca等于0的话就改lca,而且一个lca最多改一次。然后发现这玩意很可以用树上启发式合并,然后复杂度就能过了。

01-21

  • Xor-MST
    想到最小生成树,但是发现代价是两个点的异或和,然后思考怎么能把任意两个点的这玩意排序下来,想到01-Trie,发现建出01-Trie之后就从底下到上面,从左到右依次选lca就行了,因为左边的显然更小,而且lca越靠下异或和越小,就可以直接做了。
  • Data Center Drama
    发现出边+入边是偶数这玩意的充要条件就是这玩意是个欧拉回路,所以就直接对于总度数是奇数的点之间连边就行了,然后考虑对于一个边长是偶数欧拉回路我们可以直接\(a->b<-c->d<-...<-a\)就可以保证这玩意是入度和出度都是偶数了,如果是奇数条边的话就连个自环就行了。
  • Hemose in ICPC ?
    看到范围和12次,而且显然一个区间的子区间的查询值肯定小于等于这个区间,所以感觉可能是二分,于是往可以二分性的一维东西上想,又想到能把图转换成数列的玩意,想到了欧拉序,然后就出正解了,直接跑欧拉序,然后对于这个序列先询问一次最大值,然后直接二分就行了。
  • [ICPC2022 Xi'an R] Tree
    不难观察到操作1就是删掉一个链,操作二就是删掉所有叶子节点,然后发现如果想只用操作1把当前的树删没的话就是当前的叶子节点个数,然后就很好做了,直接每次删掉当前的所有叶子节点再重新计算哪些是叶子节点就行了,在这个过程中算ans的最小值。

然后又在南外上写了几道区间dp

01-22

  • Omkar and Last Floor
    发现肯定同一列的1越多越好,考虑区间dp,设\(f_{l,r}\)表示在l到r列的得分最大值,考虑l,r中间的某列k,考虑跨过第k列的且区间在l,r之内的区间,把他们的1都放到第k列就行了,然后进行区间dp就好
  • P4766 [CERC2014] Outer space invaders
    发现跨过某个时间的所有区间肯定用这些区间里最大的R来消灭,考虑区间dp,\(f_{l,r}\)表示把区间包含的所有区间都消灭的最小代价。考虑这个区间里包含的R最大的值所在的区间,然后在这个区间里找花费R能消灭的最大的区间,但是需要离散化。
  • P7297 [USACO21JAN] Telephone G
    暴力很简单,但是\(O(n^2)\),发现优化很难,根本不会,然后看到很小的k还没用,所以想到可能跟k有关系,于是想到可以用分层图其实是在做分层图专题,考虑建\(k-1\)层,每层内部i和i+1连双向边权为1的边,我们想要对第k+1层求答案,所以把\((b_i,i)\)\((k+1,i)\)连一条边权为0的单向边,如果\((b_i,j)\)能传递的话,就建立\((K+1,i)\)\((j,i)\)的边权为0的单向边,然后对于起点是(k+1,1),终点是(k+1,n)的最短路就行了。
  • P10819 [EC Final 2020] City Brain
    能推出来式子的都是神人了。首先先跑一个最短路求出来任意两点之间的最短路,然后发现要求的两条道如果有重合的地方,那重合的地方肯定连续,因为如果不连续的话那两个连续点中间的不连续部分肯定有一条小于等于另一条,显然走更小的更优。所以考虑枚举重合的起点和终点,然后算出来对于每个重合的长度对应的最小的到起点和终点的最短路,现在考虑在哪用技能更优,发现这玩意列出来之后是个单峰函数,于是想到三分,三分完就是答案了。

01-23

  • Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
    发现他只给了22个字母没给26个,于是猜到应该跟状压有关系,所以直接先把字母压成状态,然后又看到任意序列的回文,所以猜想其实回文长啥样不重要,联想到回文的性质,发现其实只要最多只有一个出现单数次的字母就行了,加上之前的发现其实就跟异或一样,然后直接先把路线异或转成到根的异或,发现其实可以用很常规的思想转换为枚举点,然后看这个点的子树中的最大值,然后分成是否经过这个点,然后就可以\(O(n^2)\)做了,发现时间复杂度还是不够,于是用dsu on tree
  • P3224 [HNOI2012] 永无乡
    很套路啊,线段树合并+并查集就行了但是我其实早就忘了咋写线段树合并了
  • Two Permutations
    这个想不到,这个真难,首先先把a序列的哈希求出来,然后通过推式子之类的玩意我们可以发现其实如果给a都加x的话那么整个数列的和的哈希就变成了\(x\sum_1^np^{n-i}\),然后发现其实后面的求和是可以预处理出来的,所以对于加的x我们可以直接\(O(1)\)求出来,所以我们就可以把x从0到m-n加入a之后的哈希值都求出来,然后放进map里,然后考虑b怎么查,发现a是一个排列,所以可以把b先排个序然后按大小依次加入之前的在数组中的位置,然后考虑每次加入一个数之后当前有没有能对应上map里的哈希值的,如果加入了之后长度大于n了就删去最小的,然后发现这玩意很不好实现,于是考虑用一个权值线段树维护一下,就做完了
  • [ABC304E] Good Graph
    弱智题,并查集+map直接查就行了

又在南外写了几道区间dp

01-24

  • Misha and LCP on Tree
    这题挺难写的,但是思路还行,考虑两个序列的最长公共前缀,发现其实直接二分+哈希就行,但是现在转到树上了,所以比较困难,现在想怎么用\(log\)时间的玩意做,发现其实可以树剖,然后一段一段的哈希比较,如果在这一段的哈希不一样了就在这两段上二分就行了。
  • P1723 高手过愚人节
    这题其实挺简单的,想写这个的原因是我本来用的是二分+哈希想水过去,结果最后被卡了,才换的马拉车,以后有复杂度更优的尽量用更优的。
  • P1600 [NOIP2016 提高组] 天天爱跑步
    绷不住了,纯线段树合并水题,但是我这个废物调了+inf年。

01-25

先复习了一下莫队,写了两道模板题

  • P4462 [CQOI2018] 异或序列
    这种形式直接想到莫队,但是莫队的那个记录出现次数的玩意其实不仅可以当某个值用,也可以当桶用,别的直接按照莫队正常方式写就行了
  • P3758 [TJOI2017] 可乐
    发现n很小,t很大,感觉应该和图论啥的就没啥关系了,所以考虑到\(logt\)的做法,联想存图的邻接矩阵,想到矩阵,然后就很开朗了,直接矩阵快速幂就行
  • P6374 「StOI-1」树上询问
    考虑到如果z不在x到y的路径上,肯定不行,如果z就是lca的话那显然答案就是n-(x对应的那条路的lca的孩子的子树的大小)-(y的那条路的lca的孩子的子树的大小),然后考虑如果z在x或y到lca的路径上,那我们答案可以类比过来就是n-(x/y的那条路的lca的孩子的子树的大小)-(n-sz[z]),然后就没了,但是有一个比较强的玩意就是用dfs序判断x是否在z子树里的玩意是这道题最大的收获

还做了几道比较水的题。

02-03

补了补之前的题。

  • Maximum Rating
    发现有个上界和下界,然后发现其实上界和下界中间的都可以达到,所以可以直接权值线段树。
  • Expanding Array
    利用异或无限扩展(x,y),是进行“宽度优先搜索”的先决条件;于是你也不能认为,出现了相同的数就可以终止搜索,因为它可能还会对之后的结果产生影响
    更轻巧的思维方式是,考虑011/101,考虑000~111的所有数字是否可以构造出来,发现可以,于是用STL来判个重就行

02-04

省选考试,啥也不会,爆。

  • HDU6410 序列期望

    考场上想到了应该是\(O(Vn)\)的了,写出来是枚举h然后对每个区间算了,但是没写对,考完之后改了改取模和实现细节就对了。
    一定要仔细看题!一定要理解如何递推!
  • 牛客 分糖果

    赛时能写出来的是神人,赛时想到了应该是个容斥,也想到从链开始转化为环了,然后就推出来了个非常离谱的容斥,甚至还过了很多样例,结果最后错了。
    首先肯定是破环为链,然后考虑容斥,显然是所有情况-至少一个连续一样的+至少两个连续一样的……,然后就假定这个序列里有k个连续的相等的段,然后这一段全部取值相等的数里最大的取值肯定就是\(min_{i=l}^ra_i\),设\(f_i\)表示到i的时候的答案,然后加个容斥系数之类的,就能发现式子是\(f_i=\sum_{j=1}^i(-1)^{i-j}f_{j-1}min_{k=j}^ia_k\),然后考虑如何把链变成环,发现只需要考虑最后一位和第一位是否相等就行了,然后发现这样不好定这两个点的所在段的最小值,于是钦定第一个是序列中最小的,然后就可以直接减掉相同情况了。然后发现这玩意是个\(O(n^2)\)的,于是考虑优化,考虑把\((-1)^{i-j}\)转化成\((-1)^i*(-1)^{-j}\),然后考虑用单调栈优化\(\sum_{j=1}^if_j(-1)^{-j}min_{k=j}^ia_k\)这一坨,发现可以,然后就能做到\(O(n)\)

02-05

  • P10597 BZOJ4665 小 w 的喜糖
    一看到每个糖都与原来不同就想到应该能用二反之类的东西搞出来,首先我们设\(f_i\)表示至少有i个人和原来的糖果一样,别的不考虑的情况,那二反一下,答案就是\(g_0\),然后考虑\(f_i\)咋求,发现不知道从i到i+1的时候不知道放到哪,所以考虑多加一维,设\(dp_{i,j}\)表示前i种颜色j个相同的位置其他随便放的情况,发现可以这么转移

\[dp_{i,j} = \sum_{k=0}^{min(cnt_i, j)} dp_{i-1,j-k}C_{cnt_i}^kC_{sum-j}^{cnt_i-k} \]

其中\(cnt_i\)表示第i个颜色的个数,sum表示1~i颜色的个数和,转移的方程式很好想,可以自行理解,然后就能做了。

  • P6076 [JSOI2015] 染色问题
    发现这玩意很难一块搞,考虑一个一个搞,首先先考虑每种颜色至少出现一次的限制,设\(f_i\)为颜色最多有i种的情况,然后之后容斥一下就是答案,考虑用行和列的限制去求\(f_i\),首先枚举一个j表示最多使j行满足条件,然后就肯定有一个\(C_n^j\)和一个容斥系数\((-1)^{n-j}\),这个可以根据组合意义去推,然后是对于某一列选中的j行,每格都有i+1(空白)的情况,所以一共的情况就是\((i+1)^j\),但是全部空白肯定是不行的,所以还要减一,最后有m列,所以还有个m次幂,所以总的就是

\[f_i = \sum_{j=1}^n(-1)^{n-j}C_n^j((i+1)^j-1)^m \]

\[ans=\sum_{i=0}^Cf_iC_C^i(-1)^{C-i} \]

  • P10596 BZOJ2839 集合计数
    感觉很像反演,所以往那里考虑,首先设\(f_i\)表示选中的集合至少交i个元素的选集合方案数,有:\(f_i = C_n^k (2^{2^{n-k}}-1)\)
    然后就直接二项式反演就行了。

晚上是比赛,2.8h时长+没有任何大样例+题目样例过水导致T1+T2都忘却了有多组数据要清空数组和变量,导致一共挂了160pts,T1T2加起来只需要补两行的清空就能拿到的160分我却没加,引以为戒,以后多想想,养成好习惯。但是比较不好的一点就是其实要是好好想的话T3T4我觉得我能拿70+92的,但是时间太短了,所以以后还是希望来点正经的比赛。
T1T2完全不用讲了,比较简单,一个小思维题一个类似折半搜索一类的玩意,只用枚举全排列然后用初始矩阵和答案矩阵直接找就行了,好像爆搜+剪枝也能过,有点水了。。下面是T3T4的原题

  • P6651「SWTR-5」Chain
    先考虑Subtask3,发现其实只需要维护入度为0的点到i的路径数量就行了,转移就是\(f_v+=f_u\),然后转移的时候不能走\(c_i\),最后统计出度为0的合法的点的贡献就行了,算是个暴力但是赛时暴力居然挂了20,再考虑k=1的点,发现其实可以再维护一个从i出发到出度为0的点的数量,然后发现答案其实就是\(sum-f_{c_1}*g_{c_1}\),其中\(sum\)表示一个点都不删的答案,到这里其实就比较能想到正解了,就是考虑容斥,发现可以利用拓扑序,对于每个y只需要把它的\(f_y\)减去拓扑序在它前面的x的\(f_x*h_{x,y}\)就行了,最后再乘上\(g_y\)再用总答案减去就行了,期中\(h_{x,y}\)表示的是x到y的路径数量。但是这道题要注意的点是一定要把代码写的常数小一点,要不会一直被卡。
  • P6378 [PA 2010] Riddle
    一个很显然的思路是直接对于每条边连着的两个点去连另一个点的反点,然后对于每一组点都连别的点的反点,然后跑2-SAT,最后判断自己和自己的反点是否在同一个强连通分量里就行了。但是这样建图的空间是\(O(n^2)\)的,根本不行,会炸,但是居然能拿到92的高分,然后考虑优化建图,这优化方式反正我想不出来,能想出来的都是神人。你考虑原来的建图方式是这样的

    但是很多,所以考虑建辅助点来减少连边但是保证和原来的效果一样,发现可以这么建

    这样建发现和原来是等效的,所以只需要把原来的图这么建就行了。

02-06

上午改了昨天晚上考试的题,下午和晚上写容斥。

  • Devu and Flowers
    先考虑如果瓶子里的花是无限的,那有多少种选的方案,发现是\(C_{s+n-1}^{n-1}\),然后考虑容斥掉不合法的,答案即为:

\[C_{s+n-1}^{n-1}-\sum_{i=1}^kC_{n+s-a_i-2}^{n-1}+\sum_{1<=i,j<=n,i!=j}C_{n+s-a_i-a_j-3}^{n-1}-...+(-1)^nC_{n+s-\sum_{i=1}^na_i-(n+1)}^{n-1} \]

但是发现这玩意直接做复杂度是很爆炸的,所以考虑怎么优化。然后发现n很小,感觉应该是二进制枚举啥东西,于是就想到了对于\(0<=x<=2^n-1\),它的二进制中共有p位为1,然后就可以用这玩意来表示上面的一项,然后这样做的话复杂度就对了,但是求排列组合的时候可能在\(C_x^y\)中x很大,所以变换一下,发现可以把它和排列的转换搞出来,再递推做,就行了。

  • Gerald and Giant Chess
    考虑从起点到任意一个点的方案数,为\(C_{x+y-2}^{x-1}\),然后考虑怎么算到一个黑点且不经过它之前的黑点的方案,那肯定要先按x和y的大小排序,设\(f_i\)表示从起点到第i个黑点且不经过别的黑点的方案数,发现其实就是总方案数-在它左上角的j:\(f_j*C_{x_i-x_j+y_i-y_j}^{x_i-x_j}\),然后就可以处理出来每个\(f_i\)了,发现最后的答案就是:

\[C_{n+m-2}^{n-1}-\sum_{i=1}^kf_iC_{n+m-x_i-y_i}^{n-x_i} \]

  • Make It One
    首先通过观察发现从2开始的质数一直乘到17就大于300000了,这一共才7个质数。然后开始思考这道题,发现我们可以先考虑选x个数,然后让他们的公约数为i的方案为\(f_{x,i}\),然后先不管x,因为x这层与x-1和x+1没有任何关系,所以可以在最外面枚举这玩意,然后我们发现其实\(f_i\)求起来还是挺容易的,我们先预处理一个\(g_i\)表示i在这个数列中的倍数个数,这东西的处理是个调和数级别的,具体地,\(g_i=\sum_{j=2,ij<=V}g_{ij}\),然后倒着预处理就行了,然后推如何求\(f_i\),首先想到要想这几个数的最大因数是i,那必然他们要有个i为公因数,然后考虑减去最大公因数是i的倍数的,就是\(f_i\)了,所以最后求\(f_i\)的公式就是\(C_{g_i}^x-\sum_{j=2,ij<=V}f_{ij}\),然后倒着推就行了。

02-07

上午考南外的模拟赛,炸飞了,因为不知道树形dp自带的少\(O(n)\)的复杂度,以至于对着自己的正确代码想了一整个考试,最后也没打别的题的暴力,也没交题。

  • P7201 [COCI 2019/2020 #1] Džumbus
    发现其实这就是个树形dp,设\(f_{u,j,0/1}\)表示现在在j点,收益是j,当前点选或不选,发现选的方案很好转移,直接\(f_{u,i+j,0}=min(f_{u,i+j,0},f_{u,i,0}+min(f_{v,j,0/1}))\),但是好像1的比较复杂,但是可以慢慢推,首先考虑从\(f_{u,i-1,0}\)转移过来,即\(f_{u,i+j,1}=min(f_{i,i+j,1},f_{u,i-1,0}+a_u+min(f_{v,j-1,0}+a_v,f_{v,j,1}))\),再考虑从\(f_{u,i,1}\)转移过来的发现可以分成j选、不选和之前不选现在选了的,就行了。

    就是这样,然后就可以直接转移了,然后答案可以\(O(qn)\)处理也可以直接先推一下后缀最大值,然后直接二分,但是其实我觉得2e8也能过。
    T2不知道原题是啥。

    首先有个没有操作3的40分,这个很好拿,直接看最后翻转好还是不好就行了,然后考虑操作3。
    发现可以处理出来每个可能序列的逆序对数量,由于n很小所以可以求出来,然后就没有了,难度在于没人能想到要用__int128

02-08

今天做了很多比较简单的期望,主要是之前基本没做过。

  • P6669 [清华集训 2016] 组合数问题
    发现只会1000的,所以考虑看题解。发现可以用卢卡斯定理,然后发现这玩意其实可以拆开每一位,然后进行连乘,即为答案,然后发现这样的话其实只有18位,然后考虑按位进行dfs,每次只需要看当前位对于这两个数枚举的数只要i<j就是1,反之就是0呗,然后就直接dp就行了。
  • P4707 重返现世
    绷不住了,会的是神人。首先考虑min-max容斥,然后考虑dp,记\(f_{i,j,k}\)表示前i个数,选中的集合大小位j,\(\sum_{选中的i} a_i = k\),转移就很简单:

\[f_{i,j,k} = f_{i-1,j,k}+f_{i-1,j-1,k-a_i} \]

然后考虑优化复杂度,考虑到min-max容斥最后计算答案的时候的系数是\(\sum C_{T-1}^{k-1}(-1)^{T-k}\),和上面的递推式两种的递推方法结合一下,然后发现其实这俩玩意的转移是非常相似的,都是(i-1,j)和(i-1,j-1),然后就可以一起转移了,考虑增加一个维度k在计算系数:

\[f_{i,j,k}=f_{i-1,j,k}-f_{i-1,j-a_i,k}+f_{i-1,j-a_i,k-1} \]

  • FAVDICE - Favorite Dice
    其实直接考虑dp就行了,设\(f_i\)表示现在已经投了i面了的期望方案数,然后转移方程就很简单了:

\[f_i = \frac{i}{n}f_i\frac{n-i}{n}f_{i-1}+1 \]

移项,\(f_0\)即为所求

  • Game on Tree
    考虑一个排列就是操作方案,然后考虑怎么会合法,其实就是一个点的祖先在它后面就行了,然后就发现其实这个序列合法的情况就是\(dep_u\),然后总的答案就是\(\sum \frac{1}{dep_i}\)
  • P4316 绿豆蛙的归宿
    直接宽搜就行了,设\(f_i\)表示从1到i点的期望步数,然后发现这玩意不能直接推,因为我们不知道从1到i的概率是多少,所以再记一个\(g_i\)就行了:

\[g_v=g_u/out_u f_v=(f_u+w*g_u)/out_u \]

值得注意的是,不能用dfs的,因为如果dfs就不可能正确的算\(g_i\)了。

  • P5104 红包发红包
    第i个人抢到钱的大小的期望显然是x/2,快速幂就做完了。
  • P6046 纯粹容器
    n小的没边了,考虑比较大的复杂度,先对于每个i,找到它左右第一个比它大的数的下标,如果这个数想被删除,那要么li中间全没了,要么ir,然后就直接考虑左,右边的方案,再减去两边的方案就行了,最后把答案累加。
  • Vasya and Magic Matrix
    显然要先根据w的大小排序,然后对于w分成若干块,每块的答案显然一样,更新也应该在这一块全都处理完之后再更新,然后把式子列出来:

\[f_i=\frac{1}{s}\sum_{a_i>a_j}(x_i-x_j)^2+(y_i-y_j)^2+f_j \]

其中,s是i前比i的w小的个数,然后把这坨展开,发现f_j,x_j,y_j,(x_j)2,(y_j)2可以前缀和维护,然后就做完了。

02-09

  • Fish
    发现n很小,直接状压,然后考虑枚举的每个状态,0就是现在这个鱼死了,1就是还活着,然后枚举0的每一个和1的每一个,然后考虑枚举到的这个1的杀掉了枚举到的0的,然后这个1的杀死这个0的还有一个概率,所以复杂度是\(2^nn^2\)
  • Let's Play Osu!
    感觉比较无敌,先考虑如果贡献是1的话,那就比较简单了,\(f_i=(f_{i-1}+1)*p_i\),然后考虑如果是平方,该怎么做,发现\((x+1)^2-x^2=2x+1\),然后就比较能做了,考虑再维护一个\(g_i\)表示从1到i都是1的期望,然后就很好转移了:

\[f_i=f_{i-1}*(1-p_i)+(f_{i-1}+2*g_i+1)*p_i \]

  • P1850 [NOIP 2016 提高组] 换教室
    这题也是无敌,能评蓝。。直接考虑\(f_{i,j,0/1}\)表示在i,加上当前的一共换了j,当前换没换。但是转移非常长,就对于前面和现在的概率直接乘就行了。
  • P2221 [HAOI2012] 高速公路
    很2b,仔细想想就会发现根本不是期望,就是求这个区间的后缀和除\(C_{r-l+1}^2\)就行了,直接线段树维护就行了。
  • P3750 [六省联考 2017] 分手是祝愿
    其实仔细想想就能发现最优的关灯顺序肯定是从大到小看是否开着,要是开着就关上就行了。然后就考虑期望,设\(f_i\)为关到i的期望次数,即为\(f_i=\frac{i}{n}+\frac{n-i}{n}(f_{i-1}+f_{i}+1)\)然后就行了。
  • P3239 [HNOI2015] 亚瑟王
    还行,差点想出来。先考虑第i张卡被用的概率为\(dp_i\),答案就是\(\sum_{i=1}^{n}dp_id_i\),然后考虑怎么求,感觉肯定有个\(n^2\)的dp,所以设\(f_{i,j}\)表示r轮中前i个选了j个的方案数,那\(dp_i\)的式子就呼之欲出了:

\[dp_i=f_{i-1,j}(1-(1-p_i)^{r-j}) \]

但是现在还差dp的转移,但是发现这玩意其实也很简单,要么从\(f_{i-1,j}\)转移过来,要么从\(f_{i-1,j-1}\)转移过来,前面那个没选上,这个是选上了,把概率乘一下就行了。

02-15

我太菜了,一整个晚上才好好学会了树上启发式合并和点分治。

  • CF600E Lomsat gelral
    发现求的东西跟子树有关系,所以想到dsu on tree,然后发现其实就是板子
  • P4149 [IOI 2011] Race
    发现是求路径上的东西,所以考虑吧点分治,然后发现其实就是板子
    剩下的时间写了点南外的期望专题

02-19

  • Mocha and Diana (Hard Version)
    首先容易发现加边的顺序是对答案没有任何影响的。然后考虑固定一个点,先把两个森林里的相同的点的所在的连通块都和这个点不联通的都和这个点连边,这样的话第一个森林里和这个点没有联通的连通块中的点肯定在第二个森林里和这个点联通,反之亦然,然后发现现在我们只需要从两个剩下的里面每个随意拿出一个连边就行了,因为左边的与固定的点不联通的在右边肯定联通,反之一样,所以这两个集合里的点肯定在两个连通块里都没有交集。

02-20

  • Cheap Robot
    \(dis_u\)为从最近的一个加油站到u点的最小代价,考虑从任意一个加油站到u,只要能到且到的时候剩余的大于\(dis_u\),那代价一定是\(dis_u\),因为你到了之后可以从u再走到那个消耗最小的加油站再回来,这样代价就是\(dis_u\)了,然后你推一下式子。

    然后你就发现了,其实答案就是\(max(dis_u+dis_v+w_{i,j})\),然后很显然的是这个东西肯定也在最小生成树上,因为如果不在就有更优的了,然后只需要预处理出来这个最小生成树再对每次询问跑倍增就行了。现在难点来到求\(dis_u\),你发现如果对每个加油站都求一遍单源最短路时间复杂度会炸,所以就建一个超级源点连上所有的加油站再从超级源点开始跑就行了。
  • Move and Swap
    容易得到一个\(O(n^3)\)的dp,\(f_{i,j}\)是红的在i,蓝的在j,然后你枚举蓝的从哪里转移过来就行了。考虑怎么优化,发现蓝的在哪并不重要,因为它可以从上一层任何位置转移到这一层任何位置,所以只枚举红色在的位置,如果不交换那就直接比较和这层最大值和最小值分别做差,取最大值和上一层更新这一层就行了,但是发现如果交换的话就得枚举j了,这显然是无法接受的,我们先考虑把交换的式子列出来

    然后我们发现这玩意其实只是这一层对这一层的转换有影响,所以可以每层先记录两个的最大值再更新,然后就做成\(O(n)\)
  • Complete the MST
    发现最优的肯定是只替换一个边,然后分讨,如果有一个环,这个环上没有被赋值的,那肯定往这个环上换一个这个边就行了,最小生成树的值不变。然后看没有环的话怎么办,发现你就对于每两个连通块直接暴力替换然后找哪个最优就行了
  • Towers
    我感觉这道题是最难的。考虑肯定叶子放是最优的,我们以 \(h\) 值最大的为根,那么就至少要在两个子树里有 \(h_rt\),对于其他点,只要在子树内存在不小于自身 \(h\) 值的就可以了。然后直接对于每个点做就行了,但是感觉很难想到。。。
  • Xorcerer's Stones
    \(f_{i,j}\)表示在i,子树里异或和为j的最小代价就行了,但是要输出方案数,所以我们把这个里面记录转移到它的两个下标,最后直接递推往前输出就行了。然后考虑到对于子树大小是奇数的做和不做是一样的,又考虑到一个点如果做了,那它的孩子们就不可能做了。然后考虑是否转移,分两类就行了。具体为\(f_{i+1,j}=f_{i,j}\),这是不做的,\(f_{i+sz_i,j^b_i}=f{i,j}\),这是做的。

02-23

  • Up and Down the Tree
    你发现如果u里叶子节点距离u小于k的话那就能无损跳出。

    其中\(f_u\)表示跳进u的子树里的贡献值,然后答案就是从根到任意一个叶子节点的最大值。
  • Strange Operation
    发现对怎么删计数很难,所以考虑记最后的可能方案。考虑记录两个1之间的零的个数,发现一段1不可能全消掉,然后考虑这一位选填1还是0,如果是1的话就到下一段记录,如果是0且现在填的0的连续个数大于原数列的了的话就找后面第一个段长大于等于当前连续个数的段,然后跳过去转移,这个第一个大于的可以用单调栈求出。难死了,想不出来
  • 外星人
    首先发现如果你模了x,那你再模比x大的就没有任何用了,所以那部分可以乱模。然后先考虑怎么计算最大的传递值,发现只需要\(f_i \to f_{i \ mod b_j}\)就行了,最后直接找最大的。现在考虑怎么计算次数,发现其实能和前面那个一起转移。你考虑先把数组排序,从i转移到比它小的j的贡献其实就是 \(\frac{(N_i-1)!}{N_{i\mod a_j}!}\),N表示前缀和。然后直接转移就行了。
  • Expected diameter of a tree
    容易想到概率是诈骗,其实答案就是两棵树的所有连边方式的直径长度和/(siz_x * siz_y),然后发现重复的两棵树的询问的答案是相同的,所以考虑用map记录,现在考虑怎么计算答案,考虑某种连边的直径是啥,发现很显然是\(max(len_x, len_y, mx_x+mx_y)\),其中前两个就是这两个玩意所在的树的直径,后面那个就是树种距离x最远的点到x的长度,前两个是固定的,所以变的其实就是后面俩,考虑使用双指针解决,然后发现可以二分,就可以做了,现在感觉复杂度是\(O(n^2logn)\),但是其实不然,因为大小小于\(\sqrt{n}\)的树的个数只有\(\sqrt{n}\)个,所以本质不同的询问只有n个,而且有记忆化,所以最后复杂度就是\(O(n\sqrt{n}logn)\)

03-06

  • Transmitting Levels
    很好的一个思路,首先发现如果能走肯定不会开新的,所以可以对于每个k先用双指针求出来从每个点开始不从新开始的能到的最远的点,记为\(to_i\),然后考虑暴力,肯定就是枚举从哪个点开始然后跳一圈比最大值,但是你发现其实任意一个\(i\)\(to_i\)这一段是不可能被别的段包含的,也就是从任意一个点开始走都会走到\(i\)\(to_i\)之间的一个点,然后就想到其实可以变换起点,只需要把这一段之间的每个点当成起点然后算一下最小值就行了,用鸽巢原理可以发现最小的那一段的长度肯定小于等于\(\frac{n}{ans}\),每次找一遍值的时间可以近似成\(O(ans)\),时间就对了。一定要学会简化冗余的枚举,要尝试通过归纳来寻找相似点以找到时间更短的做法。
  • Pudding Monsters
    这道题之前写过,但是题单里有,所以就又写了一遍。首先把输入改成\(a_x=y\),然后就把二维的限制搞成一维的了,然后就能发现合法区间满足\(max-min=r-l\),然后就是新东西了,考虑从左到右枚举r,把\(max-min+l-r\)用线段树维护,考虑线段树上的一段[L,R]什么意思,显然意思就是当前的左端点在[L,R]内的最小值及最小值个数。每次直接查询区间以枚举到的r为结尾的等于0的个数就行了。考虑每次r右移一位的直接影响,显然就是整个区间都减一,再考虑间接影响,就是\(max\)\(min\)会改变,那其实只需要更新一下最小值一集最小值的个数就行了。要尽量把多维的限制变少,要尽量把无序的限制变成有序的,这样会更好处理,要善于用数据结构。
  • Good Subsegments
    发现就是上一题的加强版,考虑直接把询问区间离线下来,按右端点排序,然后就差不多了,但是你现在统计的就不是全局的答案了,而是一段的答案,那也很简单,你就找这一段区间里的就行了。多和别的题的思想联系。
    学了道板子,线段树分治。

04-12

要重新拾起日记了。
先写重要的吧。
晚上打AT,不难发现我一打这种时间很短的比赛就会变得很唐,比如今天的C:减一个数之后不加p,D:反复ctrl+z导致后面写的回到前面之后改完忘加了,然后调了好久。幸亏今天没报rated,要不得更紧张(但是今天如果我报了rated的话就能涨好多。。幸亏E题一遍过了,要不然我就真崩溃了。其实仔细一想这些题如果不是考试可能都是不到3min就能出思路,20min左右就能打完的题,但是到了考试就会因为心理原因而变得难了起来,所以其实锻炼的还是心态,要让自己的心态和对于这种思维题的熟练度慢慢涨起来。
白天写了两道线段树优化建图,一道2-SAT,两道单调队列优化dp,一道斜率优化,之前老师说dp是最简单的我还不信,但是其实真的dp就是靠练的,这种类型的做多了就是很好就能盯出来,勤能补拙吧。
还有就是数据结构还得多练,总是写不对,不管是小的还是大的,总会有几个不管是边界问题还是代码问题的小错误,多改。
要记的是有哪些你感觉比较巧妙的题或者比较难的题和你一天的感受,自己的不足。

  • ABC401E Reachable Set
    比较好想,肯定要枚举k,然后发现上一个k会对下一个有影响,具体就是:先记录一个答案,从上一个答案转移到下一个之后,如果这个点在之前要被删掉,那答案先减一,很显然,因为他现在不被删了,然后考虑这个点的贡献,那就是它能遍历到的所有之前没被遍历到的大于它的点,这些都是能暴力求的,复杂度是均摊\(O(m)\),然后考虑怎么判断无解,发现其实也不难,只需要再维护一个并查集,在每个点加入的时候遍历它连接的边,找出连接比他小的点的边然后判断1 ~ k是不是在同一个块内就行了,值得注意的是,并不需要每次判断1 ~ k,可以记录一个指针,记录上次到哪里就不在一个块内了,下次就直接加完边之后从这里开始判断就行了,复杂度也是均摊的,还有一个值得注意的点,就是就算这个点无解也要进行上面的计算答案操作,因为它在后面是一直在要求的那块里的。
  • ABC401F Add One Edge 3
    直径的题一般都挺像的,你只要知道关于直径的一些结论就很好做了。看到题首先想到一个结论:以一个点为根的这颗树的最大深度就是两个直径的深度中的最大的那个。然后你发现如果固定了\(i\)\(j\)那你其实就能\(O(1)\)算出答案了,就是\(max(max(d1,d2),fz_i+fd_j+1)\)期中\(d1,d2\)是两棵树的直径,\(fz_i,fd_j\)是第一/二棵树中以i/j为根的最大深度,显然这两个数组是可以做到O(n)求出的,先找到树的直径的两个端点,然后以两个端点为根扫一边树并记录下来每个点的深度,最后取最大值就行了。然后你发现虽然这样了,但是复杂度是\(O(n^2)\)的,因为你要枚举两棵树的每个端点来计算答案,于是开始想怎么优化,就发现其实很好做,因为顺序并不影响,你可以先对两个数组都排个序,然后你遍历第一个数组,发现\(fz_i+fz_j+1>max(d1,d2)\)这个式子,对于i递增的时候j是单调不增的,那就很好做了,直接一个双指针找到对于当前的i对应的最小的j就行了然后答案就很好计算了,对于这个i,\(fd_j\) ~ \(fd_m\)这一段是要加到答案里去的,所以你对于\(fd\)数组做一个前缀和,然后直接加就行了,至于\(fz_i+1\)\(max(d1,d2)\)都要计算几次就都很简单了
  • ABC401G Push Simultaneously
    一眼二分答案题,你先处理出来每个点对的距离,然后直接按距离排序,二分一个答案,然后判断是否合法,判断的条件也比较简单,主要是要看能不能每个人都匹配上一个按钮,考虑到n很小,我们每次可以二分到边的边界之后直接暴力加边,然后进行二分图匹配。

04-20

做了一下昨天因为模拟考而没打的ABC,感觉难度正常,还不错。

  • ABC402E Payment Required
    这数据范围和这个题面一眼就是让状压的,因为每个问题之间没有关联,所以就状压,然后考虑一个dp数组\(f_{i,j}\),表示选择的集合i,当前还剩的钱j,这里有一个小tip,如果你考虑从当前位置怎么转移的话那你发现自己还可以转移到自己就无限循环了,所以考虑怎么转移到当前位置,那显然就是自己没做对+别的选自己,到这里思路就很明显了,三层循环,一层是之前都做了哪些题,一层是现在还剩多少钱,一层是枚举哪些点可以转移过来,就做完了。
  • ABC402F Path to Integer
    感觉比E简单,你发现一个位置你如果选他的话那对答案的贡献是一定的,那就是\(a_{i,j} * 10^{2 * n - i - j}\),然后我们就成功的把按位做变成了加法,然后发现这个数据范围和这个\(2*n - 1\)很有搞头,你发现你是可以爆搜n个数的,然后就想到折半搜索,就做完了。

5-1集训

很多考试,很难,也是参加的第一个NOI培训,也是很难。
第一天的考试拿了30pts,至今也只改了T1,太难了。
第二天考试拿了145pts,其实应该是170的,但是题目的数据范围给错了以至于调不出来,改数组大小就过了T1是原,T2的70pts是状压的分+部分分,说实话不太难,但是正解确实没敢挑战,正解是dp,其实不太简单,但是也没想象中的那么难,感觉是前三天最简单的场了,145只能拿10名。
第三天考试拿了40pts,T2没调出来,结果是自己想假了哈哈哈,以后再也不胡乱挑战T2了,好好打点部分分然后去刚T1就行了。
第四天上午讲的贪心,讲的是啥??掉线了好久。。。下午讲的dp还好点,晚上做了三道题,一个是俩dp缝起来,一个判断是否可行,一个全局dp,第一次见俩dp缝一块的。一个是无敌凸性题,当你实在做不出来的时候就直接猜凸性,然后就会发现真的有。一个是一道比较水的状压,比较好想但是有点难写,就当练手了。
后面是三天考试,之后有时间把考试的全补上。
想了很久还是想把考试的改过的题都写一下。


  • 机器人大师

    你发现最小化不如最大化好做,所以转换成最大化关门时间,然后其实就是分讨。
  • 出发 - 出发 :前面是人那人就能关门,那就等价于在前面那个人的点权上加a
  • 返回 - 返回 :后面是人那前面的就能关门,那就等价于在后面那个人的点权加上a
  • 出发 - 返回 :如果都是人就不用管了,要不然就在俩的边上加a,如果这是同一个人的就得在点上加了
  • 返回 - 出发 :这个都不用想,肯定前面的要关门,就等价于前面点权加a
    然后你就dp就行了,求一个点集使其中的点权+边权最大,直接dp就行了,但是空间开不下,要滚动数组。

  • 食物链

    场切,但是是因为之前写过。。
    你先考虑如果 \(k = 0\) 你该咋做,那你直接设一个 \(f_i\) 表示有多少个入度为0的点能到这个点就行了,然后答案就是$$\sum_{out_i = 0}f_i$$
    其中 \(out_i\) 表示一个点的出度。
    然后你考虑 \(k = 1\) 的时候你咋做,发现你只需要再维护一个 \(g_i\) 表示这个从这个点出发能到达的 \(out_j = 0\) 的点有多少个,然后就是

\[sum - f_i * g_i \]

其中 \(sum\) 是不删边的答案。
然后你考虑 \(k = 2\)的时候咋做,你发现这俩点只可能有俩关系,一个是在同一条链上,一个是不在,显然不在的话他俩是不会有交集的,所以俩分别减就行了,但是如果在的话就得小容斥一下了。我们设 \(x\) 是更靠前的, \(y\)是更靠后的,然后再记一个 \(d_{i,j}\) 表示 \(i\)\(j\) 的方案数,那么答案就是

\[f_x * g_x + (f_y - d_{x,y}) * g_y \]

然后考虑不限制 \(k\) 的咋做,发现你需要延续 \(k = 2\) 的解法,所以你需要拓扑,然后在拓扑的时候向上面一样减去 \(d_{x,y}\) 就行了,你发现 \(k\) 很小,所以可以在外面提前拓扑并且记录一下,然后直接 \(k^2\) 做这个事情就行了。
总复杂度就是 \(O(nm + k^2)\)


  • 直径

    这个赛时写了70,感觉还可以。
    先说一下70的状压做法吧。
    直接找到直径,然后你只对于选的边在这个直径上的进行计算,不在直径上的选的边你不计算答案,但是你发现这玩意他的顺序是不一定的,你直接枚举可能会错我不知道会不会错我没有试,所以你就用一个队列更新你的状压到的东西就行了。
    然后是满分的做法。
    你设 \(f_{i,j,k}\) 表示在直径上选了编号为 \(i\)\(j\) 的边,然后填了 \(k\) 个边,那么转移就是

    其中 \(b_i\) 表示 \(i\) 连了多少边。
    就没了。

  • 切题

    首先有个 \(Gale-Ryser\) 定理,然后你发现合法的条件就是

\[\forall x \in [1, n] \sum_{i = 1} ^ x a_i \leq \sum_{i = 1} ^ m \min(b_i, k) \]

然后你就对于每个操作,拿线段树维护一下前缀和就行了,值得注意的是,对于 \(b\) 的更改需要特殊注意,因为上面呢个式子要对b进行排序,所以你后面每一步都不能使 \(b\) 无序,所以你要每次更改值的时候找到和要更改的值相同的一段的两端,再根据具体是加操作还是减操作确认是左端还是右端,然后在序列上和线段树上更改。


  • 单身狗的复仇

    首先先转化题意,就是从这个序列里找到一个上升的连续段,并且任意两个点 \(i\), \(j\) 之前不能存在一个 \(k\), 使得 \(a_i < a_k < a_j\),首先可以想到一个 \(O(n^2)\)\(dp\), 考虑优化,题目要求的是某一时刻所有前缀最小值的不可差分信息,于是使用单侧递归线段树维护。

    \(i\) 很不好维护,所以维护 \(p_i\),然后就用扫描线之类的做一下就行了。

  • 智慧树

    首先能想到一个 \(O(n^2)\)\(dp\), 对于每个点记录当前的子树的颜色出现最大值和一共出现的点,然后挨个转移就行了,
    因为是子树上的问题,所以可以用启发式合并,然后你就会以为做完了,但是其实不然,因为你需要记录最大值,所以你要开 \(map\), 然后你还要转移,所以要用 \(vector\),而且是对于每个节点都要开,所以你会 \(MLE\), 但是你直接滚动 \(vector\) 就行了。

  • 四元组

    好题,原是P9850
    为了改这道题我还去学了无向图三元环计数和四元环计数。
    正向不好做,所以容斥掉蓝色子图,直接算红色子图就行了,直接算不容易,所以可以反演, \(g_i\) 为恰好有 \(i\) 条是红的, \(f_i\) 是至少有,然后考虑怎么算答案,发现就是 \(g_0-g_6 = f_0-f_1+f_2-f_3+f_4-f_5\),然后考虑怎么计算 \(f\)数组。

    然后你写一个三元环计数和四元环计数就行了。



  • 考试的时候看错题了,对着错误题面和样例玩了3h也不知道咋出来的,最后感觉是题出错了去看了一下题,才知道是自己读错题了。。
    就顺着我赛时思路写吧。
    首先先手玩几个单调的数据,然后发现不管你用什么顺序,最后的操作数总是相同的,然后你思考能不能推广到一般形式,发现显然可以,因为这个是每个单调的组合起来的,你把一段处理出来之后发现又称单调的了,所以就行了,所以现在变成了模拟题,直接做肯定是 \(O(n^2)\) 的,然后你可以线段树上二分之类的优化到 \(O(nlog)\), 但是这样仍然过不了,因为数据时 \(1e7\) 的,所以要 \(O(n)\), 不难想到把一段相同的合并成一段,然后你从后往前扫的时候每次最多分割两个,所以均摊是 \(O(n)\) 的,然后就做完了。

  • 游戏

    不难发现那个 \(n^i\) 就是唬人的,因为你不可能在不取模的情况下算出来这玩意,所以仔细一想这玩意其实就是个n进制,所以这个题就是让你最大化倒过来的字典序。

05-21

学习了平衡树的衍生的东西,学了fhq-treap,并且把很多板子都用fhq-treap重新写了一边

05-25

把最近几天写的题都总结一遍吧。

  • A Simple Task
    看数据范围,发现应该是状压,所以很容易就想到一个dp:\(f_{i,j}\) 表示选的点集是 \(i\),现在在点 \(j\),这里钦定从 \(i\) 里最小的点开始的,那么符合答案的状态就是 \(k=lowbit(i)\),其中 \(k\) 是j能到的下一个点。
  • 采花
    不难发现在一段区间里,只会有个数大于等于两个的有贡献,那我们不妨就钦定第二个是有贡献的。考虑将询问离线,按 \(l\) 排序,然后每次移动 \(l\) 的时候就计算删掉 \(l\) 的贡献,具体就是如果它的后面还有至少两个相同颜色的就不管。统计答案用树状数组。
  • 庆典
    你发现这个题的性质就是你把它缩点之后把能符合要求的三条边简化掉一条,那不就是树吗,所以直接考虑在树上怎么做。
    先考虑 \(k=0\) 的情况,那就是计算出来 \(s\) 在图上能到的点和 \(t\) 在反图上能到的点取交集
    那么对于额外加边的询问呢?假设加的一条边为 \(u→v\),如果 \(u\) 在起点的子树内,那么 \(v\) 所在的子树也可以从起点到达,也就是说,起点可达的范围可能会变成不包含的两棵子树。反过来对于终点,如果 \(v\) 在终点到根的路径上,那么点 \(u\) 到根的路径也会变为终点可达的范围,最终就有两条路径的范围。然后直接暴力计算就行了。
  • NOIP2015 充满了希望
    你发现对于一个询问,能影响的只有最近一次覆盖它的操作和最近一次交换操作,所以你直接用线段树记录一下这个就行了,然后对于每个区间的询问,直接离线按 \(r\) 排序然后直接做就行了。
  • 天天爱射击
    整体二分
  • Sums of Sliding Window Maximum
    有一个比较显然的思路是,对于每个数,可以先用单调栈计算出左边第一个大于它的数的下标和右边的,然后你对于每个点的左右计算出的边界端点一个个枚举,算出区间长度并相加,但是这样会错,因为如果有两个比较大的且值相同的,他们会重复计算,所以我们把任意一个的边界定义为大于等于而不是大于就行了。
    现在考虑怎么优化。发现可以只枚举 \(L_i\) ~ \(i\),和 \(i\) ~ \(R_i\)中长度较小的,然后差分另一边,这就是启发式分裂,复杂度被证明为 \(O(n\log n)\) 就做完了。
  • 寻宝游戏
    通过手摸,不难发现答案的计算方式:
    设把关键点按照dfn序排序后的数组为 \(a_1...a_k\),然后答案就是 \(2(dis(a_1,a_2)+dis(a_2,a_3)...+dis(a_{k-1}, a_k))\),然后就很简单了,你考虑加一个点的贡献,如果本来就有这个点,那不变,没有的话就在数组里二分出来这个点的左右两个点,答案直接加上 \(dis(x,y)+dis(x,z)-2dis(y,z)\) 其中 \(x\) 是当前点,\(y\) 是第一个小于 \(x\) 的点,\(z\) 是第一个大于 \(x\) 的点,把序列拿 \(set\) 维护一下就行了(第18个自己想出来的紫)。

最大收获是询问要多想离线,多用启发式,多想二分。

05-26

  • Sue 的小球
    首先能想到 \(O(n^3)\)\(dp\),然后你发现枚举 \(k\) 是多余的,只会从左,右端点转移过来,然后就减掉一维,就没了。
  • 二叉查找树
    牛牛牛。
    这道题最牛的点是你不管怎么变,树的中序遍历的顺序是不会变的,还有就是权值的改变不能有重复的权值,这是很假的,因为能改的数是实数,这一位不行就小数,所以这个是个假的不能重复。
    于是就有一个非常显然的区间 \(dp\)\(f_{l,r,k}\) 表示这颗子树的中序遍历的区间是 \(l\) ~ \(r\),里面所有结点的权值都 \(\leq k\),然后我们再枚举一个点作为当前的树的根,再分两种情况(一种是根节点不改变权值,一种是改变权值)直接转移就行了。

最大的收获是在变化中找到不变的东西来维护,还有就是有些东西并不需要在乎形态,有些状态可以多枚举就不用管了,复杂度能对就行了。

05-27

有三道比较显然的蓝,看了就会了,感觉没啥用写的就不写了。

  • Pre-Order
    其实跟昨天的二叉查找树差不多,也是树的形态和遍历顺序拍成的序列的关系,考虑 \(dp\),设 \(f_{l,r}\) 表示这段内以 \(l\) 为根的方案,你直接枚举下一个和它同级的根,那显然就是要么就是 \(r + 1\),要么就是 \(a_{rt} \leq a_{i+1}\)
  • Linear Kingdom Races
    这题一眼就不是区间 \(dp\),但是可以用区间的思想。设 \(f_i\) 表示考虑到第 \(i\) 条路的答案,有两种转移方案,一个是不选,那就是 \(f_i=f_{i-1}\),另一个是选一段,\(f_i = max_{j=1}^{i-1}f_j+val(j+1,i)-cost(j+1,i)\),其中 \(val(j+1,i)\) 表示把这段的路都选上能对答案造成多大贡献,\(cost(j+1,i)\) 表示把这段的路都选上的代价。然后你发现这玩意可以直接用线段树维护,具体地,对于每个 \(j\),你维护 \(t_j=f_j+val(j+1,i)-cost(j+1,i)\),每次直接按照 \(val\)\(cost\) 的贡献直接区间更改值就行了。

06-01

写了一下昨天的ABC,不出意外的话能写到F,G确实比较偏构造了,没想出来,但是别的题都还是比较简单的。

  • Minimum OR Path
    不难想到按位贪心,你考虑最先的答案是 \(2^30\),然后从大到小考虑这一位能不能不要,如果可以的话就减去,判断也是简单的,用并查集即可。
  • Athletic
    你考虑一个数,它连接比它至少小 \(D\) 的数,单向边,然后你发现这个图就是一个 \(DAG\),那么答案就是从每个没有出边的点到每个没有入边的点的长度的最大值,这个玩意暴力求是平方级别的,所以考虑怎么优化。
    不难想到每次转移肯定都是从较小的点向比它大的点转移,所以你就直接从最小的点往大遍历,每次只需要用线段树维护一个这个点当前的最大转移值,然后对于每个点的更新,你就在它的合法区间里找最大值并且加一更新它就行了。
  • A/B < p/q < C/D
    牛题。
    对于一组的不等关系,你先尝试把他们的左右两边的分式都变成真分数,然后再取倒数,接着这么干,直到有一个是假分数,一个是真分数,然后这时的答案就是中间的分式等于1,然后你不断向上迭代出原本的答案就行了。
    因为 \(p\) 变小时, \(q\) 也会变小,然后答案又满足最优子结构,如果你不满足那肯定会有一组答案时分母比你小,分子比你大,显然无解。

06-03

  • 一直在你身旁
    发现区间 \(dp\) 的暴力是显然的,然后你发现,\(k\) 向右移动时,\(f_{l,k}\) 单调不减,\(f_{k+1,r}\) 单调不增,然后用单调队列做一下就行了。
  • Ciel and Gondolas
    首先有一个三次方的 \(dp\),比较好想出来这个是有决策单调性的,既然决策点是有单调性的,那就直接分治优化一下就行了。
  • Yet Another Minimization Problem
    跟上一道题一样,只是转移不太一样
  • 序列分割
    首先通过手摸发现分开的顺序没有用,然后就有一个 \(dp\) 了,感觉是个凸包,斜率优化就没了

06-05

06-06

  • T-Shirts
    不难发现对于每个人做的话会很难,所以直接考虑对于每个T恤做,然后你对于T恤都排序,对于大于 \(c\) 的东西都减 \(c\),并且把他们的答案都加一,但是你发现你需要维护T恤的相对大小,然后你发现每次重新减了再排序是肯定不行了,但是你发现顺序的改变只会每次只会把 \(c\)\(2c\) 的点插到小于 \(c\) 的里面,然后你发现你只需要按 \(c\) 排序,复杂度就对了,因为区间慢慢变小,所以这个就是 \(log\) 的了,你还要维护序列,所以要用平衡树,所以最后是俩 \(log\)
  • Nauuo and Bug
    难点在于计算 \(-p\) 次数,所以肯定要改变思路。

    用线段树维护即可。
  • 对数据结构的爱
    和上一道题一样,但是狗屎的是这玩意严重卡常,根本卡不过去,所以你得不用 \(vector\),然后还要把线段树换成指针跳跃少点的玩意,才能过。

06-07

  • Zero-Sum Ranges 2
    困难计数题。
    \(f_{i,j,k}\) 表示表示目前加的层里我一共放了 \(i\) 个点,产生了 \(j\) 个区间和为0个区间,有 \(k\) 个间隙

    但是前缀和可以是负数,所以你把 \(f_{i,j,k}\) 对应成 \(f_{2n+1-i,m-j,k-1}\) 就成了。
  • kangaroo
    简单计数题。
    抽象一下题意,就是有多少排序,满足头是 \(s\),尾是 \(t\),然后对于 \(i\),要满足 左右都比它小或者左右都比它大。
    这不就纯纯是连续段 \(dp\) 吗,考虑加进一个数,可以新开一段,也可以合并两段,都没有啥限制,但是不能加在一段之后,因为这样的话就会一个大于一个小于。
    但是新开一段的话需要考虑能不能放在头尾,如果大于 \(s/t\) 的话就不能放,因为这样的话 \(s/t\) 就不能放在端点了。
  • Prufer 序列
    板子。
  • 树的计数
    对于树的计数,一般会用到 \(Prufer\) 序列,所以我们要找打这个序列和题目中的 \(d_i\) 的关系
    而在 \(Prufer\) 序列中出现 \(d_i-1\)的点在原输入中就是 \(d_i\) 了,然后就是简单计数题了。

06-19

  • rsraogps
    首先势能分析一下,发现这三个操作都是只会进行 \(O(log)\) 次修改,所以我们只需要记录上次被修改的时间以及值,这样就能做到 \(O(1)\) 查询了。
    然后思考一下怎么做这个东西,仔细想想就会发现这个东西肯定要离线做,所以我们先离线下来,按 \(r\) 升序做
    当确定一个 \(r\) 时,我们记 \(s_i\) 表示 \(l \leq i\) 时的方案数,然后你差分一下就行了。
  • 等差子序列
    首先可以发现的是这个题是个诈骗,我们显然只需要找一个长度是3的等差数列就行了。
    肯定是枚举三个数里中间的那个。
    然后这里就是一个比较套路的东西,你对于值域开一个桶,然后对于枚举过的数就把他们在桶的位置赋成1,然后你就对于枚举的这个数跑一下看看有没有不是回文的串就行了。
    如果没有回文的,那就是一个比它小 \(k\) 的在一边,另一个比它大 \(k\) 的在另一边。
    判断是不是回文可以用哈希,用线段树维护更新和查找就行了。
  • Three Occurrences
    把这道题的问题分解成两部分。
    一部分是快速查找当前区间的数是不是都只出现了三次
    另一部分是区间里是不是所有数都出现了小于等于三次
posted @ 2025-01-20 21:55  Rose_Lu  阅读(26)  评论(0)    收藏  举报