5196. 【NOIP2017提高组模拟7.3】B
4674. 【NOIP2016提高A组模拟7.21】Clock Sequence
1322. 硬币游戏
5819. 【NOIP提高A组模拟2018.8.15】 大逃杀
5821. 【NOIP提高A组模拟2018.8.16】 手机信号
线段树已经会做.
剩下就是set 的事了.
只需学会如何使用operator即可,记住set左闭右开的.
5864. 【NOIP2018模拟9.11】很多序列
可以发现如果两个构造的数在摸 x 1 x_1 x1意义下相同,保留最小的一个数即可。
所有直接上 S P F A SPFA SPFA,所有点都在摸 m m m意义下,转移时直接由点 x → ( x + a i ) % a 1 x\rightarrow (x+a_i)\%\ a_1 x→(x+ai)% a1
最后最大值减 x 1 x_1 x1就是答案了.
5344. 【NOIP2017模拟9.3A组】摘果子
典型的树形依赖背包,然后可以用经典的方法解决:
当然还有一种用 d f n dfn dfn序的方法,其实也是类似的:
5343. 【NOIP2017模拟9.3A组】健美猫
很容易想到直接按照题意加数据结构树状数组模拟,常熟贼小.
然而实际上,这是一道可以仅凭耐心做出来的题,仔细观察每当下标往右移一位时,所有数与下标相减的变化.
是可以做到 O ( n ) O(n) O(n)的。
【NOIP2016提高A组模拟9.4】树上摩托
直接枚举子树大小 k k k,然后判断是否有 n k \frac{n}{k} kn个点的节点的 s i z e size size是 k k k的倍数.
O ( n l o g n ) O(nlogn) O(nlogn).
5196. 【NOIP2017提高组模拟7.3】B
点分治裸题.
先计算小于等于 S − 1 S-1 S−1的路径方案数。
二分一个在 S ∼ E S\sim E S∼E中的阈值 T T T,再看看减去 S − 1 S-1 S−1的方案是否还有即可.
1110. CQOI2009循环赛
一道极其猥琐的搜索题.
好吧,实际上是我太弱.
我们可以加很多个优化,然鹅依然无法在1s的时间内通过这道题.
所以实际上需要一个记忆化!!! 我们可以设 f [ i ] [ S ] f[i][S] f[i][S]表示还剩下 i i i个人没有配对成功,剩下 i i i个人的hash状态为 S S S时这个方案是否可行。
这样直接搜索,事实上是比较复杂的.
然鹅我们可以用搜索套搜索的方式去更加简洁地实现.
5898. 【NOIP2018模拟10.6】距离统计
点分树强悍做法.
假设现在询问只有一个,那么一个极显然的做法就是二分一下答案 a n s ans ans,然后点分治即可.
询问有 m m m个,所以我们需要强悍的点分树.
我们处理好每个分治中心管辖的范围,然后对于每一个询问,我们像先前一样二分ans.
只不过这个时候,我们要在 l o g 2 log^2 log2的时限内达到.
也很简单,我们统计过当前询问点,以及过它所在的分治中心(总共有log个)的条数.
也就是直接在那个分治中心的管辖范围的序列上二分即可.
因为这样会算重,所以对于每一个点,我们需要算两遍:
这种点分树的方法非常强大,需要好好领悟.
然而大佬lzw提供了一种它的牛逼二分方法,这种方法时间复杂度与上面做法是一样的,都是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n).
事实上,可以对于每一个点分别记录两个值 l , r l,r l,r,然后类似二分答案一样,不过对于每个点二分的答案都不一样,对于每个点,要二分的值实际上是 l + r > > 1 l+r>>1 l+r>>1.
这样做完一遍树分治之后,调整 l , r l,r l,r的值,即如果一个点已经得到的路径数多了,那就把 r r r改小,否则把 l l l增大.
5943. 【NOIP2018模拟11.01】树
因为有关位运算,很容易想到按位处理.
因为是与运算,所以没进行一次计算, 1 1 1的个数只会减少而不会增多.
那么可以在线段树上暴力修改,每修改一次, 1 1 1的个数都只会减少,否则没有必要往下修改嘛.
所以势能分析一波,就是 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)的了。
5947. 【NOIP2018模拟11.02】初音未来(miku)
考虑最简单的冒泡排序.
每次找到最左边的一对相邻逆序对进行交换,直到没有为止,线段树的每个叶节点相当于是一个01状态表示与其相邻点(下一个点)是否需要交换.
同样是势能分析,同样是线段树上操作,哎。。。
【NOIP2018模拟10.30】阻击计划
又是一年DP题.
注意到题目最重要的一个性质:点度数 ≤ 10 \le 10 ≤10.
那么容易想到状压一个点连出去的边.
现在考虑以 k k k然后考虑一条非树边进行的影响,至多是两条边,且会产生一个贡献,把这看成一个物品(也是一种物品).
另一种物品则是一条边不被非树边覆盖时的贡献,其实就是子树的f最大值.
然后背包一下即可.
原谅我这是口胡的,所以只有自己能看懂。。。
POJ2054
略屌的一道贪心题.
考虑树上权值最大的点,必定是在其父亲染色完之后立刻染色,那么实质上可以把这两个点合并起来,权值为两点权值的平均值
一直做下去,以后新产生的点,权值就是所有原始权值除以点数.
证明:http://www.cnblogs.com/rainydays/p/3271277.html (非常牛逼)
HDOJ 4699 Editor
我发现自己做这种需要一点点智商的题很弱啊.
还是需要多思考.
类似对顶堆,我们搞一个“对顶栈”.
光标的左移和右移实质上都可以转化为两个栈栈顶的变化.
5958. 【NOIP2018模拟11.8A组】秘密邮件
要把 S − → T S-\rightarrow T S−→T,那么考虑 S S S中一些相同的数.
这些 S [ i ] S[i] S[i]要移到的位置其实是知道的,对应 T T T串的顺序,如 S = { 1 , 2 , 3 , 2 , 1 } , T = { 2 , 1 , 3 , 1 , 2 } S=\{1,2,3,2,1\}, T=\{2,1,3,1,2\} S={1,2,3,2,1},T={2,1,3,1,2}
那么第一个 1 1 1就要移到第 2 2 2个位置,第二个 1 1 1就要移到第 4 4 4个位置,把 S S S串的每个位置用其对应位置表示,容易发现,这个新序列的逆序对个数就是答案了!
5384. 四维世界
很经典的一道题,先考虑二维。
然后转化到三维,令 f [ i ] f[i] f[i]表示到第 i i i个点,且不经过以前所有点的方案数.
直接用总方案减去不合法就行了.
假设从一个点 ( 0 , 0 , 0 ) → ( n , n , n ) (0,0,0)\rightarrow (n,n,n) (0,0,0)→(n,n,n),总方案必定是 ( 3 n n ) ∗ ( 2 n n ) \binom{3n}{n}*\binom{2n}{n} (n3n)∗(n2n)
5957. 【NOIP2018模拟11.7A组】scarborough fair
很经典的一道DP题。
单独计算每个联通块的贡献.
正难则反,用总的减去不连通的即为联通的期望.
f ( s ) f(s) f(s)表示 s s s这个点集不连通的概率.
又是经典套路,枚举编号最小的点所在的子集 t t t,那么 f ( s ) = ∑ t ∈ s f ( t ) ∗ P ( t , t − s ) f(s)=\sum_{t\in s}f(t)*P(t,t-s) f(s)=∑t∈sf(t)∗P(t,t−s)
P ( t , t − s ) P(t,t-s) P(t,t−s)表示 t t t点集与 s − t s-t s−t点集之间没有边相连的概率.
这个可以 O ( 1 ) O(1) O(1)计算出来,其实就是 T ( s ) T ( t ) T ( s − t ) \frac{T(s)}{T(t)T(s-t)} T(t)T(s−t)T(s), T ( i ) T(i) T(i)表示 i i i这个点集内所有边都不相连的概率.
https://jzoj.net/senior/#main/show/5354
主要是第二问有点麻烦.
这个处理还是比较经典的。首先,假设直接连边,那么是一个DAG,对于这个DAG直接贪心是不一定最优的。所以要想办法转化成二分图。这里的经典操作就是拆点,把一个点拆成 A ( 连 出 点 ) , B ( 连 入 点 ) A(连出点),B(连入点) A(连出点),B(连入点),一个点的 A A A连向其他点的 B B B,然后做一遍最大图匹配即可.
http://www.51nod.com/Challenge/Problem.html#!#problemId=1061
这题最主要的一个性质就是一个超级合数一定可以由一个比他小的超级合数乘以某个质数得来。
所以用一个堆去储存一下这些超级合数,每次把堆顶取出来,与已经取出来的数的约数比较一下,如果当前取出来的堆顶是超级合数,那么就把它乘以一些合法的素数得到新的素数扔进堆里.
按照障碍点进行DP。令 f i f_i fi表示从 ( 0 , 0 ) → 第 i 个 障 碍 点 (0,0)\rightarrow第i个障碍点 (0,0)→第i个障碍点且仅经过这一个障碍点的方案数,显然可以通过 f j ∣ j < i f_j|j\lt i fj∣j<i容斥一下转移过来.
问题变成从一个点到另一个点不穿过对角线的方案。运用对称的思想推组合数,任意一条不合法的方案,即对应着一条经过 y = x + 1 y=x+1 y=x+1直线的方案。所以组合数减一下就可以,发现其实就是卡特兰数。
事实上可以直接暴力拆式子。考虑用一次方和,二次方和……六次方和去维护答案即可。实际上也可以用线段树去维护区间。因为每次的询问都可以看做是原序列排完序后的一段区间。
考虑背包合并即可。因为有最小值,还要随便记录算一算就好了。
首先这道题如果连好边后用最简单的支配树去做。复杂度是 O ( ( N + M ) L o g N ) O((N+M)LogN) O((N+M)LogN)的。所以关键在于连边。
而对于连边,有一个很经典的秀操作就是用线段树去优化。具体地说,我们维护一颗主席树。每次新建一个点的时候,把新建的一条链向上一个版本对应的点连一条边(如果没有对应的点显然不连),然后把这条新建的链向这个新建的点连边。最后,我们把这个点向它查询的 L o g Log Log段区间连边即可,这里我们只需要向上一个版本的这 L o g Log Log段区间,显然就完美复制了原图的连通性。做一遍支配树即可。
还有一种不用线段树优化连边的办法。我们直接做。因为我们要求的是当前这个点在支配树上的深度,本身我们只需要那些连向点的 i d o m i idom_i idomi的 L C A LCA LCA。那么我们按拓扑序去做,每次做完一个点的idom之后把它在线段树上对应的log段区间更新一下,更新成新的idom的LCA。然后求一个点idom时也是直接查询覆盖这一个点的区间的那些LCA即可。实际上更简单更好写。
我自己的分块做法:按序列分块。用三颗线段树维护。二分答案。复杂度 O ( m n l o g 2 2 n ) O(m\sqrt{n}{log_2}^2n) O(mnlog22n)。lihui神仙
的分块做法:按权值分块。对于每个权值我们维护一颗线段树,比如说对于一个操作 [ l , r , c ] [l,r,c] [l,r,c]我们就在第 c c c棵线段树上修改区间 [ l , r ] [l,r] [l,r]即可。
然后我们再按权值分了块之后给每个块对应一个标号。那么一次修改操作我们也把对应的标号线段树上的区间 [ l , r ] [l,r] [l,r]修改即可。这样我们查询的时候先跳大块,跳不动了再一个个跳。时间复杂度是一个根号一个log,又好打又优秀的。
当然,另外一种方法就是直接树套树去做。外层的是权值线段树,内层就对应序列的。然后每次查询直接在权值线段树上二分,判断左右儿子的答案即可。时间复杂度两个log。
最后,还有一种方法就是整体二分。我们考虑二分一个 A n s Ans Ans,把当前序列依次扫过去。每次扫到一个询问的时候看看对应区间里有多少个数,决定把它放到左边继续递归还是右边继续递归。这个也是两个log的。当然,如果用树状数组去维护区间的话,常数贼小贼快贼秀。
4238. 【五校联考5day2】纪念碑
关键字:扫描线、线段树、贪心
做法很奇妙、很巧、很棒啊!:https://jzoj.net/senior/index.php/main/download/4238/SOLUTION1.pdf/0/solution_path
3198. 【JZOI2013】蚂蚁寻路
关键字:DP
不知道为什么考场没有想出来。其实是一道很水的DP题。
令 f x , y , k , p , 0 / 1 f_{x,y,k,p,0/1} fx,y,k,p,0/1表示到第 y y y列, 0 / 1 0/1 0/1表示是凸的还是凹的, x , k x,k x,k分别表示上届、下届, p p p表示前面有多少个凸的。可以做到 O ( 1 ) O(1) O(1)转移。
时间复杂度 O ( n 3 k ) O(n^3k) O(n3k).
3195. 【HNOI模拟题】数学
关键字:分治
分治一下。然后乱搞。处理一下。线段树、二分、单调?
总之要码量++。回家改题的好选择。
【ARC063E】Integers on a tree
考虑记 f i , j f_{i,j} fi,j表示以 i i i为根的子树,如果 i i i这个节点填 j j j时,子树是否能合法。
当节点 i i i没有固定的数时,转移很显然是 ∩ v ∈ S o n i ( f v , j − 1 ∪ f v , j + 1 ) \cap_{v\in Son_i}(f_{v,j-1}\cup f_{v,j+1}) ∩v∈Soni(fv,j−1∪fv,j+1)
有固定的数则直接记录即可。考虑用bitset压位,时间复杂度就可以做到 O ( N 2 32 ) O(\frac{N^2}{32}) O(32N2)了。
事实上不用这么笨。直接对每个点记录一个范围即可,易知如果一个节点的子树中有一个点已经确定了,那么这个节点的值一定是一段连续的奇数或偶数,从下往上推即可。
时间复杂度 O ( n ) O(n) O(n)。
事实上,对原图可以进行适当的简化。
度数为1的点可以直接让答案乘上 ( k − 1 ) (k-1) (k−1)。度数为2的点实际也可以缩。
假设 x x x连向 a , b a,b a,b。然后三条边分别为 ( a 1 , b 1 ) , ( a 2 , b 2 ) , ( a 3 , b 3 ) (a_1,b_1),(a_2,b_2),(a_3,b_3) (a1,b1),(a2,b2),(a3,b3)。事实上是可以缩成 ( a 3 ( a 1 + a 2 + ( k − 1 ) b 1 b 2 ) , b 3 ( a 1 b 2 + a 2 b 1 + ( k − 2 ) b 1 b 2 ) ) (a3_{(a1+a2+(k-1)b1b2)},b3_{(a1b2+a2b1+(k-2)b1b2)}) (a3(a1+a2+(k−1)b1b2),b3(a1b2+a2b1+(k−2)b1b2))
其中 ( a , b ) (a,b) (a,b)的初值为 ( 0 , 1 ) (0,1) (0,1),这是不考虑当前点的颜色的情况下。所以最后dp的时候要考虑颜色。
现在问题转化为了有一幅图,每条边有两个权值,分别代表两个顶点颜色相同和不同时的代价,最后所有代价乘积即为一种贡献。然后直接搜索一下就好了。
终于可以搬一道题了。反正oj上没有。
其实就是求 ∑ i = 1 N ∑ j = 1 i ( i + 1 ) ( j + 1 ) [ ( i , j ) = 1 ] \sum_{i=1}^N\sum_{j=1}^i(i+1)(j+1)[(i,j)=1] i=1∑Nj=1∑i(i+1)(j+1)[(i,j)=1]直接思路是反演。但实际上还有其他方法。可以运用一些小技巧得到两倍 A n s Ans Ans的答案,是一个类似于 ∑ i = 1 N μ ( i ) i k \sum_{i=1}^N\mu(i)i^k i=1∑Nμ(i)ik的式子。然后这个式子是可以做到 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)的。运用狄利克雷卷积即可。
6080. 【GDOI2019模拟2019.3.23】IOer
生成函数的妙用。Howarli %%
真的很妙。
实际上只有最后一步比较难懂,但感觉找找规律应该也能发现 f i = 1 ( i − 1 ) ! f_i=\frac{1}{(i-1)!} fi=(i−1)!1,所以应该还是可以做的。
可以直接上三分。注意转化模型,三分小数比较繁琐,不如直接三分整数,然后求对应的小数。
当然可以直接运用 下 取 整 ( a − b ) = a − 上 取 整 ( b ) 下取整(a-b)=a-上取整(b) 下取整(a−b)=a−上取整(b)这个性质,注意只有当 a ∈ Z a\in Z a∈Z时成立。
第二问类似,只不过要推一下式子,最后根据这个性质化成一条二元二次式子,然后枚举一个值,把另外一个做主元,求一下极值即可。
可以说是一道简单题吧。不知道为什么想了那么久。
就设一个 f i , j f_{i,j} fi,j表示 T T T串到第 i i i个位置, S S S串到第 j j j个位置的最大匹配。
然后分两步转移:
f i , j = f i − 1 , j − 1 + 1 f_{i,j}=f_{i-1,j-1}+1 fi,j=fi−1,j−1+1,即 S i , T j S_i,T_j Si,Tj能匹配时。
否则,如果匹配不了,那么就从 j j j往前,看看第一个出现的字符,预处理一下,反正可以很容易算出 f i , j f_{i,j} fi,j的值。
FFT:相同深度点 与 {w} 做卷积。
然后经典套路,把下标用最大的深度 h h h,替换:
原本是: 深 度 d 答 案 = A n s d = ∑ n a n ⋅ w n + d 深度_d答案=Ans_d=\sum_na_n·w_{n+d} 深度d答案=Ansd=∑nan⋅wn+d,替换成 A n s d = ∑ n a h − n w n + d Ans_{d}=\sum_{n}a_{h-n}w_{n+d} Ansd=∑nah−nwn+d
这样就能在 h + d h+d h+d位搞出答案。
半平面交:
对于每个点都做半平面交,然后走最短路出去。
LCT :
按照边权排序。
然后考虑维护一颗树。
每次删去最小(早)的边即可。
维护的值也是最小是多少,然后可以直接把这个值对应的边给删掉。
我的想法是枚举两条分界线,即往下最长的在哪一列,有多长,往上最长的在哪一列,有多长,这样是 O ( n 4 ) O(n^4) O(n4)的,然后算其他的地方就发现只需要分类讨论+预处理即可。
都可以用ETT维护。具体来说,ETT就是用splay来维护括号,splay上每一个点代表一个左括号或者右括号。键值就是这个括号是第几个。
然后就可以很容易地把一操作转换为求LCA,二操作转换为splay上二分前缀为k的最后一个点,三操作就是把两个括号之间的扔到它祖宗去。