emmmm,把以前写的2b总结丢上来吧,不过应该也不会有人看QAQ
(注:因为用txt写的,有一些公式打的很随意,放到markdown上公式自动排版,有可能会显示出错误!可在下方留言)
2019.2.24
如石子堆交换这种改变状态的可以尝试看看差分
在取数使满足某一条件最小或最大时可以先假设原来状态,然后表示出取某一个的状态,用作差或作商看在什么情况下更优
2019.2.26
对于最短路问题,题目中说可以有几条边直接免费,这是经典的分层图最短路(如https://www.luogu.org/problemnew/show/P4568 [JLOI2011]飞行路线)
可以设dp[i][j]表示到i这个点,共用了j次免费的机会,在dijkstra里加一个当前用了多少次免费即可
最后的答案不是dp[t][k],是min(dp[t][0…k])
2019.2.27
同余类最短路想明白了,举个例子,比方说就像每次让你判断一个数x能不能表示成给定的数的完全背包的形式,就是先取一个模数m,通常为给定的中的最小值,然后思想就是假设尽量多的
取m,也可以看成每m个分成一块,最后还有x%m不能被表示,因为我们一开始是假设尽量多的都取了m,所以现在我们只要除了m以外的数能表示成km+(x%m)的形式就可以了,当然要判一下
k不能大于x。
这样不就转化成了%m的类的了嘛,做最短路,t向(t+a[i])%m连边,dis[i]表示能表示出的km+i最小的k,只要它<=x就有解
done
2019.3.1
对于全局的一种规划,比方说一种调度,交换,可以尝试网络流模型。日后再填坑
UVA11613 Acme Corporation
这类题目要拆点,很经典。就是当一个点转移出现与题意不符时。比方说这道题,必须把每个月拆成两个点,一个表示生产,一个表示卖。
因为生产的可能要留着接下来e个月卖,如果只有一个点的话,往后连边,那所有的点就都联通起来了,有可能就超过了k个月才买
1011 [HNOI2008]遥远的行星
2019.3.3
ZROI:
给你若干个a,让你求不同k/a的个数(k 考虑把所有a约分以后,设分母为d,则最简真分数有phi(d)个,所以只需枚举d,看是否为某一个a的约数,然后加上phi(d)就行了
对于这种一看就很phi的问题,可以往约分、phi计数上凑
Trick:一般对于一个数,一个一个枚举它的因数(就是把它分解掉)往往不够快速,可以枚举一个数,把它的倍数里存上这个数
给你若干个数a,让你求恰好有k个值为a/b(整除)相同的最小的b
Tips:a/b的个数有O(sqrt(a))个,显然吧
对于本题,可以先统计出对于每个数a,a/b不同的最小的b,这个小Trick可以用b=a/(a/b)+1来跳吧
然后排序去个重,然后枚举每个b,暴力看a/b相同的个数
时间复杂度O(sqrt(MAXA)*n)
只想到普通暴力,这类问题很难想到其他方法,就只能暴力优化,可以想到减少重复计算,对于一些b,a/b的值相同的被重复计算,可以用如上“取使a/b不同的b的最小值”来跳掉
2019.3.4
对于插头dp这样转移可能要考虑条件比较多的问题,一定要在纸上列出
2019.3.5
BZOJ1003: [ZJOI2006]物流运输
一开始以为要拆点,把每个点拆成n个点,分别表示n天能不能通过,然后可以的话就连边,然后费用流,YY了一下,感觉应该能做吧,以后再填坑吧(咕咕咕)
然后正解明显要简单一些,要多做一些dp题了,感觉dp很不熟练蛤
个人认为本题精辟在于cost函数的设计,cost(i,j)表示i到j天都跑同一条路,最短是多少,这样转移就很简单了吧(枚举最后一次换路)
BZOJ1004: [HNOI2008]Cards
首先一眼群论吧,Burnside引理,但是不能直接polya,因为每种颜色有限制,这很好办吧,先暴力拆一下循环,然后背包看一下能分配的方案数,很显然,这就是不动点的个数,
但是坑点:就是不使用任一种置换变换,也要做一次,最后的置换个数也是m+1,因为不变换也是一种置换QAQ。
一般群论的题都要想一想这个坑点QAQ
~~晚安
2019.3.6
部分无根树问题可以考虑转prufer序列,它两是一一对应的关系,比方说无根树计数,实际上就是计算满足条件的prufer序列个数
例:
BZOJ1005: [HNOI2008]明明的烦恼
当成一个prufer序列,则每一个度为x的点会在prufer序列中出现x-1次(这个可以分这个点是不是最后剩的那两个点讨论一下就出来了)
然后不就是组合数啥的了QAQ
upd.高精度除法太麻烦,由于方案数一定是一个整数,可以先分解质因数在运算
BZOJ1006: [HNOI2008]神奇的国度
问题实质:给你一个无向图,用最少的颜色染色,使得相连接的两个点颜色不同
第一眼感觉像网络流,编不下去了……QAQ这是一道cdq的一道论文题23333,
叫最大势算法,就是说每个点先给他一个顶标0,然后每次取顶标最大的一个去掉,然后把与他相连的点顶标加一,然后出现过的顶标种数就是答案
https://blog.csdn.net/qq_35205305/article/details/51823348 代码真的很巧妙啊
最近感觉都没什么码力了鸭QAQ
BZOJ1007: [HNOI2008]水平可见直线
第一次做计算几何,要么全场AK,要么全场不会,显然这是一道全场都会的题吧QAQ
显然能看见的应该是一个类似下凸壳一样的东西,按斜率排个序,栈维护一下就可以了吧
BZOJ1008: [HNOI2008]越狱
肯定是用总的方案数-不能越狱的方案数好算鸭
总的方案数很显然mn,不能越狱的方案数m*(m-1)(n-1),就是每个人我们不要同时考虑它和两边的人相不相同,只考虑和左边,第一个人有m种,因为接下来n-1个人只需保证和左边相同
所以是那玩意,然后快速幂不就行了嘛QAQ
2019.3.7
BZOJ1009: [HNOI2008]GT考试
第一眼觉得是组合题QAQ
f[i][j]前i个字符,i-j+1~i都和那个玩意匹配的方案数,然后可以用类似kmp的适配方法转移
n 1e9,结果……要矩乘优化……,这很好理解吧,每一个f[i][j]都要从f[i-1][]转移来的,而且只要失配的一样(j一样),那么转移要乘的系数也就一样。
所以我们可以kmp一次以后构建转移矩阵
done
upd.主要能矩乘的原因是因为这是计数问题,然后从f[i][]只能统计入f[i+1][],且只要失配的个数一样,接下来转移要乘的系数也一样
md,我真是zz,明天一定要学会cdq分治了,周六的时候把主席树看掉
2019.3.8
在考虑分治鸭这类的时候,一定要假设递归时已经把两半给完成不用考虑了,总是在这一块欠缺
2019.3.9
cdq分治懂了,就是先按住一维排好序,然后在分成左右两部分递归分治,然后就只用统计左半对右半的影响就行了,这个可以用类似归并排序的方法往树状数组里统计……
最后再把这个序列变成有序的,因为这个序列已经处理完,接下来要处理的跟本序列内部的相对顺序没关系了
BZOJ1011:[HNOI2008]遥远的行星
这道题是近似……有点瞎搞,就是当i比较小的时候暴力,大的时候因为分母最小是i-1,最大是i-Ai,因为Ai很小很小,所以i当很大时更是相对小到可怜,所以可以把所有分母变成
(i-A*i)/2直接算
BZOJ1012: [JSOI2008]最大数maxnumber
只想到线段树,当然也可以,但是有点麻烦了,可以用单调栈,因为后面的一进来,如果前面有比他小的,那么前面的就没有用了,所以可以用单调栈记录下标,然后lower_bound就好了
BZOJ1013: [JSOI2008]球形空间产生器sphere
首先看到n+1个方程n个数就应该有点想法,因为都是完全平方公式,把2~n+1个方程和分别第一个方程做差就变成了n个方程,n个未知数的一次方程,高斯消元即可
BZOJ1014: [JSOI2008]火星人prefix
splay裸题但我还是给写萎了……每个点维护他这颗子树所表示的子串的hash值,然后就是splay了
Tips.前后要前后要多加两个点,因为在截取子串的时候会用到i-1和j+1
BZOJ1015: [JSOI2008]星球大战starwar
冰茶鸡(并查集)倒着删边变加边
2019.3.10
BZOJ1016: [JSOI2008]最小生成树计数
一开始听说是矩阵树,不会
后来看题解说因为保证了每个权值最多出现10次,所以可以用并查集+dfs
考虑kruscal的过程,假设当前两个块已经联通,要想强行加入当前边,必须删掉之前的一条边
要想依然保持最优,删掉的边必须要和这条边的权值一样
这样我们就得到了两个结论
1.同一幅图的最小生成树中所有相同权值出现的次数均相同
2.相同权值的一些边构成最小生成树的连通性相同
所以我们可以先做一次最小生成树,统计每个权值出现的次数,然后可以dfs看每个权值选那么多个能构成联通且无环的个数
(注意是dfs回溯,所以假设选了当前边,把两块连在了一起,然后dfs,回溯后要把两块分开,这是大多dfs容易漏的地方)
然后根据性质2,把这个权值的能连起来的连起来
ZROI正睿NOIP半年训练 day 10 C. 【19寒假普转提】图
这道题很难,上午很自闭,当时的想法是枚举一条为k的最短路,剩下的用计数方法添加,结果发现太假了
看了解析也很久才明白,明天上午还要再YY一遍
首先的思路应该是给每一个点枚举一个从1到它的最短路的值d,然后可以考虑:
对于点j,若d[j]
并且肯定有一点j,d[j]
但是这样显然是n^k级别的,想一下,我们并不需要具体知道到每个点的最短路(因为是完全图嘛),只需要知道最短路为某数的点有多少个,最后再用有重复值的排列数一乘就是方案数了
所以我们枚举最短路为x的点有多少个,当前已经处理过y个点了。对于大于k的点都当成k+1就行了,因为反正它对最后的最短路d[n]不会有影响的
这就把n^k优化到了整数拆分的复杂度(相当于把n个点分给k+1中颜色)
说到底就是让你枚举限制,然后看满足这一限制的边有多少种方法
Tips.只是这样是有问题的,因为前面说过必须有一条边cost=d[i]-d[j],直接乘法原理相乘有可能会使所有边都大于这个,简单容斥一下就行了吧
对于k+1型的边不用容斥,因为它本来可能就不是k+1,可能是k+1到L内的任何数(意思是至少是k+1,emmmm为什么不用容斥这里可能有点难理解),我们都是可以接受的
2019.3.11
ZROI D. 【19寒假普转提】道路建造
感觉比T3还好想一点呀,可以证明任一个符合要求的图不可能由两个不同的欧拉图通过添或减某一条边得出(反证法呼啦一下不就出来了吗)
也就是说我们只要欧拉图计数就行了,然后乘上C(n,2)就行了(就是选两个点,在它两间添/删 边)
欧拉图计数就是容斥,考虑先在2~n间任意连边,显然2^(C(n-1,2))种方案,这时把每个奇数点与1连一条边即可
此时2~n点都以保证不是奇点,因为一个图不可能有奇数个奇点,所以1也不可能是奇点,所以此时该图是“欧拉图”
也就是说2^(C(n-1,2))中连边方式均对应唯一一种方案使得该图是“欧拉图”
不,有一点问题,这些点可能不联通,所以要容斥一下,减去满足所有点都是偶点但不联通的图的个数
蓝书第二节提了一个类似的
设f[i]:i个点组成欧拉图的个数
因为该图不连通,故枚举第一个点所在连通块的大小(1~n-1,要是n就连通了),此时要减去的应该是
第一个块因为已经保证是一个联通块了所以应该是f[j]*C(n-1,j-1),关键是接下来的点我们要保证它每个点都是奇点就可以了
这里我zz了,又去缠scape…… 前面推导过了n个点保证每个点都是偶数点的方案数是2^(C(n-1,2)),所以……n-1个点……我太zz了
BZOJ1017: [JSOI2008]魔兽地图DotR
这道题真的挺难的,一个晚上才弄懂QAQ 一开始以为就是就是一个裸的树形背包……太naive了
考虑一般的树形dp基本都是用父节点更新子节点,但这道题父亲是依赖于儿子的
那如果还是用二维f[x][y]表示x这棵子树共花了y元钱能得到的最大效益就假掉了,因为你就不知道有哪些是用来直接装备,有哪些是用于合成父亲
那就……添一维吧f[x][j][y]表示有j个x贡献给合成父亲了,那么考虑转移
对于低级物品,就是一个完全背包吧
对于高级用品
首先也要枚举做了i件x 吧
我们要从x的儿子中买到必须的东西来合成这j个必须的x,剩下的钱再自由组合使得效益最大
那就设g[tmp][o]表示从x的前tmp个子树中花了o元钱,且用于合成i件x的都要买够,剩下的钱能买到的最大效益
显然可以用背包求出吧,再滚掉一维g[o]=max{g[o-p]+f[tmp][num[tmp]*i][p]};(枚举p为在第tmp棵子树砸的钱)
最后合并给f[x][j][y] =max{g[y]+(i-j)*val[x]};
最后因为可能是森林,所以要对于每个根完全背包一下(枚举总共花了多少钱和这棵树砸多少钱,显然吧)
2019.3.12
BZOJ1018: [SHOI2008]堵塞的交通traffic
讲真的,用线段树维护连通性这玩意还真没想到,当时第一眼想的是可持久化并查集(然鹅我也不会,捂脸)
2n的图,对吧。是不是就像一个方块一样啊,就跟一条线区别不大,只是把每一个元素看成是一个21的了,所以可以考虑线段树
每一块维护这个方块四个角的联通情况,六种对吧,在维护两个东西,mid->mid+1这这两块两行的联通情况,因为线段树嘛,需要把两个儿子往上合并,这时候首先要两个儿子都联通鸭,对吧
然后再分类讨论怎么合并,,,注意每一块维护的联通情况都是必须在当前块里面走,不能出块绕一圈
考虑如何统计答案(假设出发点y小,且分别在第一行和第二行,不然swap一下),有四种情况
1.直接朝目标走,此时只能向右,下,上方向走
2.先向左走一段距离,然后向下走,再向右走到出发点下面的位置。此时在直接走到目标,只能向右,下,上方向走
3.先只能向右,下,上方向走,等到了目标点y坐标相同的再向右,再向下,再向左,这样绕一圈
4. 2,3结合先向左绕一圈,再走正常路,再往右绕一圈,
真的,有一点绕QAQ
2019.3.13
BZOJ1019: [SHOI2008]汉诺塔
因为优先度规定,所以每一步都是确定的,进而整个过程都是确定的,所以就是让你求最小时刻2或3柱子上堆满
显然模拟要fst吧,这个状态的转移貌似可以通过一些的组合,所以就试试dp吧
设g[i][j]表示将j柱子上的i个全部最先移到某一根柱子是哪一根,f[i][j]就是将他们移到g[i][j]的步数,设a=g[i-1][j],b=1+2+3-a-j
1.g[i-1][a]==b 这个可以先把i-1个移到a,这时候因为刚完成,所以不能再继续移动这一根,所以可以把第i个从j移到b,肯定是合法的对吧,然后在把i-1跟移到这个b
f[i][j]=f[i-1][j]+1+f[i-1][a] g[i][j]=b
2.g[i-1][a]==j 这个要先把i-1个移到a,再把第i个移到b,然后把i-1个移回j,把第i个从b移到a,最后再把i-1个从j移到a
f[i][j]=f[i-1][j]+1+f[i-1][a]+1+f[i-1][j] g[i][j]=a
下午补一下计算几何的基本点积和叉积之类的晚上争取把那个计算几何题给A了(已经想明白了,就是计算几何那个地方不会写)QAQ
来填坑了:
BZOJ1020: [SHOI2008]安全的航线flight
第一眼二分,可以考虑二分答案,然后在每个点覆盖一个圆,看能不能把整个线路都覆盖
编程复杂度太高,不会,看了莫涛的论文,迭代,思路很妙
考虑每一条线段,设左端点L最近点L1,距离s1,右端点R最近点R1,距离s2
从线段上找到一点mid(显然可以二分去找,对吧)使得mid到L1,R1的距离相等
这时候如果mid到L1(R1)距离小于了ans,这个线段就不用考虑了(因为此时往左边或往右边会更小对吧),不然拆分成L到mid和mid到R两条线段
重复这样的步骤,不断向下迭代,正确性显然吧
2019.3.14
总是在自主推题的时候啥都不会QAQ
BZOJ1021: [SHOI2008]Debt 循环的债务
首先我们规定不会a给了b一张钞票,b又把它给了c,如果这样就让a直接给c就行了
这样我们就初步发现,其实每个人不需要知道他的钱是谁给他的,只需要把不够的钱填满就行了
初始三人各有sa,sb,sc元,这样py交易了几次以后看能不能有ta,tb,tc元钱
每种面值的钞票肯定是互相独立的,所以可以dp解决,对吧
f[i][j][k]只有前i种面值能互相转移,a共有i元钱,b共有j元钱,需要的最小交易票数
枚举转移后第i种面值a,b的拥有量即可转移
BZOJ1022: [SHOI2008]小约翰的游戏John
一看就很博弈,好像还挺naked?QAQ Anti-Nim
Anti-Nim的provement贴一下rqy的blog
https://www.cnblogs.com/y-clever/p/6667592.html
这里想总结的就是博弈游戏的题,可以自己先推一下必败态(必胜态),这很好推吧,看一下最后结局时的状态,然后可以以此分为Nim-Sum是否为0设一下规则
接下来证明每一个必败态所有后继一定是必胜态,所有必胜态至少有一个后继会是必败态
ps.wyy说Anti-Nim不咋重要吧,题不多
BZOJ1023: [SHOI2008]cactus仙人掌图
这题第一次见,看着题解YY了都挺久的QAQ,不过,还好,终于……
仙人掌图可以用一种叫做圆方树的东西来处理
简而言之就是把一个环变成一个点,原来环上的每个点除了第一个点跟新点连条边,再把新点和第一个点连一条边
这时候就是一棵树了,然后就树上dp?
不,有一点问题的,就是环上的情况
环上可能是两个点他们的子树和他们构成最长链(想一想理解一下)
这个可以用单调队列来解决了对吧,这两个环上的点距离一定<=环长的一半,因为两点距离是最短路,可以考虑枚举第一个点,然后单调队列维护接下来环长一半的序列的最大贡献,显然
一开始这个地方没有想明白,YY了好久QAQ
2019.3.15
BZOJ1024: [SCOI2009]生日快乐
mdzz,现在对题目感觉越来越差了
第一眼二分,发现不好验证吧
注意n只有10……小学爆搜题……
考虑每一步横着切还是竖着切,且每一半分给多少人,枚举一下搜。不过只需要枚举到一半就行了,因为切开以后两半上的操作就是相独立的了,分给大于一半的话对调一下就行了
upd.下题为3.15所写,3.16补坑
BZOJ1025: [SCOI2009]游戏
首先很显然就是n拆分数的lcm个数,这个玩意……
假设这个lcm=p1^k1 * p2^k2 *p3k3*……ptkt
很显然{k}就是对应每个{p}的最高次,我们现在只需要让p1^k1 + p2^k2 + p3^k3 +……+ pt^kt<=n即可
证明(瞎YY一下):
因为如果出现某质因数不是最高次,那么他也就没什么用对吧,还不如换成1,都一样
会不会出现多个p的最高次乘成一个数呢,这也不用考虑,举个例子
因为都是质数,都>=2所以 pi^ki *pj^kj >piki+pjkj
所以这个时候每个都拆成质因子的幂最划算(反正最后多的位置都可以补1嘛)
因为只要有某一个k不一样就是一个不同的解,所以就是一个完全背包了嘛,对吧
2019.3.17
昨天的比赛题等全部测完以后在总结吧,为了表示我对它的尊重(笑)
ZROI A. Domino
显然是一个类似于轮廓线dp的东西,但是因为只有三列,所以不需要记录包含上一行的东西,记录当前行的,然后枚举上一行的状态,考虑当前横放,至于竖放,我们只考虑往上竖放
很显然zz题,我比赛的时候yy到了结果还没敢写,mdzz
ZROI B. Zuma
一眼出结果,不就是一个栈嘛,再用一个栈记录当前的最大匹配,由于一开始有一点zz,写错了(虽然数据弱,也没测出来,但是比赛后被hack),幸亏我在嘘嘘时灵机一动,把自己给hack了
就是kmp吗,用栈顶的最大匹配匹配嘛,然后把当前的压栈,当此时匹配长度为模板串长时直接把栈指针减去那个长度
ZROI C. Triangles
感动,今天的数学题终于推出来了QAQ
对于每一条边,能经过它的边的个数s,答案是对于每条边的C(s,2)的和?-
不对,有平行的边,要减去他的影响,假设k为某一个值时相同的有s2个,那么减去的贡献就是C(s2,2),然后它会经过n-s2的所有边,要乘上(n-s2)
最后因为对于每一个三角形,它的三条边我们都考虑了,所以要除以3,因为是膜意义下,所以是逆元
ZROI D. Upload
首先肯定不可能把那个程序复制下来就能A
那就考虑怎么把问题变形。
把(Ai,Bi)看成是一条边,显然一个n个点的联通块最多只能有n条边
YY: 当这n个点有n-1条边时,恰好联通,所以总会有一个点没有被选,这是如果再加一条边,显然可以把其他的调剂一下使那两个端点的某一个空出来对吧
(因为本来就有一个空位所以肯定可以调剂成功对吧)
这样就显然是一个并查集对吧,但是有一点问题就是他是要按顺序的,就是先给每一个人尽量A,不行再B,并查集的话不能保证顺序
上面说过n个点的联通块最多只会有一个没被选,那我们把它当成根不就行了嘛
因为本条限定,所以本题相连的时候谁往谁连就很重要了QAQ
BZOJ1026: [SCOI2009]windy数
第一眼看到竟然想到的是组合计数之类的QAQ
200 0000 0000 的范围还要计数,很显然是数位dp吧,求区间内的个数,显然这个满足区间减法,减一下就行了对吧
f[i][j]表示的是 i位的windy数且最高位是j的方案数(没错就是最高位,不然不好统计答案对吧)
最关键的应该是统计答案
首先肯定是位数比那个给定数小的
for (int i = 1; i <= k - 1; i++)
for (int j = 1; j <= 9; j++) ans += f[i][j];
然后是位数相同,但最高位的数比给定的小的
for (int i = 1; i < shu[k]; i++) ans += f[k][i];
最后再是相同的,这时候往下自己可以体会一下,也不太好说对吧
for (int i = k - 1; i >= 1; i–){
for (int j = 0; j <= shu[i] - 1; j++)
if (abs(j - shu[i + 1]) >= 2) ans += f[i][j];
if (abs(shu[i + 1] - shu[i]) < 2) break;
if (i == 1) ans += 1;//it is a windy number itseft
注意给定数本身就是一个windy数这种情况,对于计数问题一定要慎重考虑到每一种情况
2019.3.18
来补一下比赛前两题
ZROI A. 【五一集训】小汤圆
因为p是质数,所以x^(p-1) = 1 (mod p) 也就是说每p-1个是没有贡献的
所以 x^(r mod (p-1)) = a (mod p)
又因为题目说了r和p-1互质,肯定就有逆元对吧,假设对吧,设为rr
两边同时rr次方,左边就变成了x,右边就是a^rr ,最后取模一下,就可以了对吧
所以那个无解是骗人的
ps. r和p-1互质,所以一定有逆元,但是p-1不一定是质数,所以不能用费马小定理求逆元,要用扩欧,一开始sb的调了好久QAQ
ZROI B. 【五一集训】小z的省选
就是模拟嘛,对吧,年月日分别乘上他们的权,然后相加
年365(要加上一些闰年,这个类似容斥对吧)
月28,29,30,31
日 就是读入-1对吧
最后,因为显然这个乘出来很大,inf要到2^63 -1 ,0x7FFFFFFFFFFFFFFFLL,因为定义小了,被sb的搞掉了30pts,又不是rnk1 QAQ
2019.3.19
比赛最后一题
ZROI D. 【五一集训】甜甜圈
比赛的时候想着对着前50pts打前缀和,哪知道萎了
正解一开始还不会,想了一天,总算是对扫描线+线段树明白了一点考虑
考虑对于每一个点如果它是中心,那么他的覆盖边界看成一条线,同时意味着在这些线上,刚好能覆盖到这个点(注意,这点很重要!!!)
所以第i-r行j-r到j+r这条线权值为+s
i-l+1行(注意i-l行也能被覆盖到,我的前缀和就是这里GG了)的j-l+1到j+l-1这条线权值为-s
i+l行 j-l+1到j+l-1这条线权值为+s
i+r+1行j-r到j+r这条线权值为-s
然后把每条直线的左右端点离散化一下
按行数大小排个序,然后就是基本的线段树操作对吧,区间加和区间求最大值
upd.要把一行的所有直线贡献都操作完以后在统计最小值,不然可能有一些地方后来又有直线要减掉一个权值
mdzz,我以后再也不打div3了,题目又智障,基本都是水题,然后一半懒得打了还掉分,woc
2019.3.20
BZOJ1027: [JSOI2007]合金
这是一道神题啊……首先以为三个数和为1,所以只要知道前两个就行了
把这个抽象成点坐标,然后发现,把2个1*基础合金合成就变成了他两边上的中点,所以任意多的两个合金合成的新合金一定在他两的连边上
然后这不就变成求一个凸包能包含所有给定点嘛
就是考虑枚举每两个原始合金的连边,如果所有所求合金都在它的左边(意思就是顺时针包裹,逆时针也一样对吧)就连一条 长为1的有向边,其它的边都置为inf
然后跑Floyd
最后的min(f[i][j]+f[j][i])
有不少细节,比方说一个基础合金就能解决所有
还有当叉积为0时是在同一直线上,只有在这个线段上时才连这条边,否则不连
BZOJ1028: [JSOI2007]麻将
蓝书上讲的只有14张的时候的方法,这样只有20pts
因为按顺序枚举,所以当枚举到i,i一定要用完,所以因为>3个顺子和>3个刻子等价,所以考虑<3个顺子。
如果i是刻子,假设我们用顺子,那么显然会剩下<=2个,因此不是最优的,所以有刻子就用刻子。
或者简单点想,每次操作的是最小的牌,目标是把这个最小的牌用完,如果先用顺子可能是最后一点不能拼成刻子对吧QAQ
BZOJ1029: [JSOI2007]建筑抢修
之前wyy也讲过的,先按截止时间排序
然后按顺序操作,维护一个大根堆
如果能加的下就加,否则就用堆顶跟它的所需时间比一比哪个大,如果堆顶大,那么可以把那个任务换成当前这个,此时开始时间一样,但结束时间变早,只可能更优不会更劣对吧QAQ
2019.3.21
BZOJ1030: [JSOI2007]文本生成器
一看就跟AC自动机有关对吧
但是如果直接统计合法方案数是不容易的对吧,那就容斥呗,这就豁然开朗了
f[i][j]生成串的前i个字符且匹配到了j这个点的方案数,如果j不是一个串的结束点就可以转移对吧
for (int i=1; i<=m; ++i)
for (int j=0; j<=sz; ++j)
for (int k=0; k<26; ++k)
if (!End[Son[j][k]]) (f[i][Son[j][k]]+=f[i-1][j])%=MOD;
BZOJ1031: [JSOI2007]字符加密Cipher
很常见的trick对吧,在后面再接上一遍,然后后缀数组排个序
最后输出时只输出sa<=n的
BZOJ1032: [JSOI2007]祖码Zuma
首先基本上都有问题,简单说一下这类题的通法(虽然这不是标程?因为这道题数据就有问题,标程也有问题?)
就是一开始把连续的相同的看成一块(因为只要加了一个能达到三个就能消掉,所以连续的至少是两个对吧)
然后f[i][j]表示把i~j块消掉至少需要的代价,然后区间dp就不难了吧
BZOJ1033:[ZJOI2008]杀蚂蚁antbuster
这个就是大模拟吧,注意用可以用叉积来计算是否在线段上,然后没有什么了吧?
upd.不能简单地根据叉积正负判是否在线段上,应该看他和这条线段的最小距离是否<=0.5
2019.3.22
BZOJ1034: [ZJOI2008]泡泡堂BNB
又名田忌赛马?
solve(*a,b)表示尽量让a得分多,所以最后答案就是solve(a,b)和n2-solve(b,a),这个地方很巧妙
然后先给两边实力排个序,然后搞头尾两个指针
如果a[l1]>b[l2]那么顺理成章a这一局肯定赢了
不然的话若a[r1]>b[r2]那么a这一局也赢
如果这两个都不是的话,那么我们干脆用a[l1]去消耗掉b[r2],注意有可能两个等于
2019.3.23
md,有一些计算几何先不要写,又不会又耽误时间QAQ
BZOJ1036: [ZJOI2008]树的统计Count
裸的树链剖分吧QAQ,但是要注意,会有负数,所以统计最小值的时候……sb了QAQ
BZOJ1037:[ZJOI2008]生日聚会Party 2019.3.25 ZROI C. 数 ZROI D. 膜 然后我们用数学归纳法证明f[j][i]=ΣC(j,k)(1<=k<=i) 然后我们先算出j在1e5以内的f 2019.3.26 BZOJ1041: [HAOI2008]圆上的整点 如果试2r/d,那么a^2 + b^2=2r/(2*r/d) BZOJ1042: [HAOI2008]硬币购物 2019.3.27 BZOJ1045: [HAOI2008] 糖果传递 BZOJ1046: [HAOI2007]上升序列 BZOJ1047 [HAOI2007] 理想的正方形 BZOJ1048 [HAOI2007] 分割矩阵 P3718 [AHOI2017初中组]alter 2019.3.28 第二问看了题解好久才明白QAQ BZOJ1050: [HAOI2006]旅行comf 2019.3.29 BZOJ1052: [HAOI2007]覆盖问题 BZOJ1053: [HAOI2007]反素数ant BZOJ1054: [HAOI2008]移动玩具 2019.3.30 BZOJ1056: [HAOI2008]排名系统 BZOJ1057: [ZJOI2007]棋盘制作 2019.3.31 ZROI【17 普及 19】绿巨人的跳跃 嗯,就是那样算就行了 ZROI【17 普及 19】雷神的锤子 ZROI【17 普及 19】鹰眼的箭 ZROI【17 普及 19】超级英雄的战斗 BZOJ1059: [ZJOI2007]矩阵游戏 BZOJ1060: [ZJOI2007]时态同步
高维dp,真的没想到鸭
f[i][j][k][t]:排到第i个人用了j个男生,且从第i个往前以第i个为结尾的任意序列男生比女生最多多k个,女生比男生最多多t个
然后枚举第i个是男生还是女生
男->若k+1
最后答案sum(f[n+m][n][i][j])(0<=i
ZROI B. 糖
嗯。推对了,但是二分的时候的那个判定写出锅了
考试的时候是根据直觉大家所缺少的尽量一样多
如果要证明(YY)的话:就假设一开始都是a[i],每个人都不缺
然后从每个里面一个一个的拿,设所缺的为x,每拿走一个,怒气就增加2*x+1对吧,所以每次要取所缺最少的拿
最后的局面就会变成任意两个人所缺的差值<=1,然后二分其中小的那个差值,接下来就行了对吧,
注意二分的判定如果a[i]
这个要求每个子串的 (max-min)的和,然后根据sigma的分配率
就是求每个子串max的和-每个子串min的和
这个可以单调栈来解决
正着枚举耗时间可以反过来(就像质因数分解啥的)
枚举每一个位置作为最大值/最小值,
则它的贡献就是val*(它作为最大值/最小值的区间个数)
然后lmax,lmin,rmax,rmin表示它左边/右边第一个比它大/小的数的位置,然后乘法原理一乘不就是区间个数吗QAQ
这四个玩意可以用单调栈来求
比方说求lmax,可以倒着维护一个单调栈,如果当前元素比栈顶大就把栈顶弹掉,顺便把栈顶的lmax置为当前的位置,然后最后栈里剩的lmax都是0
其他几个类似
但是有值相同的元素,所以我们把rmax,rmin定义为右边第一个大于等于/小于等于当前值的位置
done
嗯……也是推对了式子,但是没有发现那就是一个sigma(组合数),可以二分,-70pts QAQ
f[j][i]表示用i个蛋试了j次能探索出的最高楼层
显然f[j][i]=f[j-1][i-1]+1+f[j-1][i],如果当前这个蛋碎了,说明要用i-1个蛋试j-1次确定之前的楼层,那么当前楼层显然是在f[j-1][i-1]+1最划算对吧QAQ
然后如果没碎的话把当前楼层看成1楼还可以再试j-1次对吧QAQ
归纳法证明首先就是证明初始的一定合理,然后证明某一个如果之前的合理那么当前的一定合理
首先j=1时肯定是合理的对吧
j>1时若j-1合理,那么
f[j][i]=ΣC(j-1,k)(1<=k<=i-1)+1+ ΣC(j-1,k)(1<=k<=i)
注意+1可以看成+C(j-1,0)对吧
所以f[j][i]=ΣC(j-1,k)(0<=k<=i-1)+ ΣC(j-1,k)(1<=k<=i)
而C(i-1,j)+C(i-1,j-1)=C(i,j)对吧
所以得证
如果可以就直接用f
不行就用二分j
然后根据C(i,j)=C(i,j-1)*(n-j+1)/(j-1) 每次O(M)的时间算出
也可以提前预处理出这个sigma
BZOJ1040: [ZJOI2008]骑士
首先如果每个人向他的仇人连一条边,那么每一棵树都只会有一个环(每个点出度都为1),最后答案每个树互不依赖,每个树的答案相加就行了对吧QAQ
所以那就暴力类似暴力断环一样的(环那里用一下并查集对吧,最后连上会变成环的那条边不连,给它记录下来)
最后连上的那条边,两个端点只能选一个对吧,两个都dfs一次,做根,表示不选它
f[],g[]的定义还是跟大多是树形dp一样,还表示在当前子树选/不选根的最优解
这一看就是数论吧
然后2000000000的范围通常都是要枚举约数到sqrt(n)的对吧
x^2 + y^2 = r^2
y^2=(r+x)(r-x)
设d=gcd(r+x,r-x)
y^2 = d^2 (r+x)/d (r-x)/d
设A=(r+x)/d B=(r-x)/d
显然A,B都要是完全平方数才行对吧
因为A,B都互质,所以A和B 都是完全平方数
设A=a^2 B=b^2
a^2 + b^2=2r/d
所以d肯定是2r约数,枚举到sqrt(2r)
如果d是2r约数,那么我们就试一下d和2r/d个
试什么呢?首先A,B要为完全平方数,然后还要互质,还不等
我们枚举a,
如果试d,那么a^2 +b^2=2r/d
a^2 2< 2r/d
a^2< r/d
a^2 *2< d
a^2< d/2
done
如果没有硬币个数限制的话大家都知道f[i]=sum(f[i-c[k]])的
那有了限制我们可以用容斥哇
总的-第一个超了-第二个超了-第三个超了-第四个超了+第一第二超了……
因为第一个超了,所以他至少有k[1]+1个,剩下的就随便搭配,所以是f[i-c[1]*(k[1]+1)]
这个地方之前一直弄错,容斥说的第一个超的不代表只有第一个超了,而是至少有第一个超了,这个韦恩图很容易明白对吧QAQ
BZOJ1044: [HAOI2008]木棍分割
这个第一问小学题对吧QAQ
第二问隔板法dp
f[i][j]前i个数分成j块的方案,然后提前维护一个left表示从当前这根最左能延伸到哪一根
再用s维护j-1状态f的前缀和,所以转移就变成了f[j]=s[j-1]-s[left[j]-1];
假设每个人给了逆时针方向的人b[i]个,然后把全部的都用a[1]来表示,最后转化为前缀和
因为字典序是按下标的,如果lis表示以为当前为结束的lis的话是不知道前面的字典序的
所以可以表示以i为开头的lis,倒着做就行了
然后暴力找
先找到第一个f[i]>=x的,然后把m设为a[i],–x
接下来每次都找a[]>m且f[]>=x的,重复这样的操作
这个是二维滑动窗口,上一次Claris跟我讲过
先对每一行维护以当前元素为第n个的区间最大/最小值,这个就是很基本的单调队列对吧
然后再对每一列进行同样操作,就是单调队列维护上面记录的每一行的最大/最小值
首先10的数据范围肯定让我们想到了搜索,
均方差=sqrt(Σ((xi-x’)^2)/n) x’是x的平均数
所以我们就是要求出Σ((xi-x’)^2)最小值
这个我么可以定义dp[a][b][x][y][k]表示将左上角坐标(a,b),右下角坐标(x,y)的矩形分成k个的最小贡献
分竖着切还是横着切分别枚举
枚举第一道切在那,切两部分之后还各需要切成几块
显然可以记忆化搜索,、
边界当k=1时返回(sum[a][b][x][y]-x’)^2
首先它是内个不完美度尽量小,可以二分
然后我们可以把一段颜色相同的缩成一个长度p[i]
一开始看sooke的题解贪心有问题,一到mid个就改,凭感觉都觉得有问题
应该是sum p[i]/(mid+1),每mid+1就必须要改变一个,显然对吧
然后mid=1的单独处理
两种情况很easy对吧
1049: [HAOI2006]数字序列
此真神题鸭
第一问我们可以用补集变换的思想,实际上就是用总数-最多可以不动的点数,
两个点j,i,不需要动的要求是
a[i]-a[j]>=i-j ===> a[i]-i>=a[j]-j
我们再定义一个b[i]=a[i]-i,当b[j]<=b[i]时可以转移
就是说枚举右边界i,找到最远的j使得b[j]<=b[i]&&f[i]==f[j]+1,所以所有可以转移到i的点都在[j,i]中,然后我们可以推出
对于从每一个转移点j转移到i,因为[j,i]间的数一定要么b[i](不然可以从j转移到它在转移到i就多了一次),一定有一个t使得[j,t]是b[j],[t+1,i]是b[i]
这个画一下数轴抽象成距离就好理解了QAQ
然后假设从[j,i-1]都变成b[i]的代价是sum,
那么将[j,i]处理的代价就是sum-(b[i]-b[j])*(y-x),(x,y是[j,t]中大于和小于b[i]的点的个数)
我们倒序枚举所有可能的j,b[j]一定是不减的,不然就可以多转一次(想一想QAQ)
所以我们要使y-x尽量大,这个前缀和维护一下也是很naive的QAQ
第一眼01分数规划?不对,有鬼
暴力并查集
先把所有边按权值从小到大排序
枚举最小边,我们想使最大边最小,加入比它大的边,第一个能使两点联通的边就是最小的最大边
BZOJ1051: [HAOI2006]受欢迎的牛
如果从每个人向他喜欢的人连一条边,然后缩个点
如果最后只有一个强连通分量出度为0,则答案就是这个点包含的点数
否则不存在
YY一下QAQ
一眼二分对吧
然后的贪心没想到
就是说考虑能覆盖所有点的最小矩形,肯定四条边上至少有一点对吧
但是只有三个正方形,所以有一个要覆盖两条边
此时最优的情况就要覆盖一个顶点
所以我们枚举能覆盖剩下点
第一眼用线筛求约数个数,然后……
题解说
首先答案肯定是每一个小质因数的次数都是大于等于比它大的质因数的次数的
不然交换一下它们的次数,会使得约数个数不变,但不满足约数个数大于所有比它小的数
然后考虑前12个左右的质数就行了,因为他们的乘积已经大于20 0000 0000了,然后爆搜就行了QAQ
状压BFS就行了QAQ
BZOJ1055: [HAOI2008]玩具取名
一开始觉得就四个数对吧,把它带进去迭代加深搜索不就行了嘛
然后发现这如果没有无解不就永远搜不到嘛
然后题解是区间dp(对啊,这不是很明显区间合并嘛)
bool f[l][r][s] 表示能否将[l,r]变为s这个字母
记录每一种变换
如果[l,m]可以变为a,[m+1,r]可以变为b,且有一种变换是ab变为c
那么[l,r]就可以合并为c
明显平衡树对吧
然后怎么维护名字,更新时间和更新值呢
hash,建成一个链表,如果两个名字hash值一样就暴力比对
然后平衡树每一个节点都指向hash链表中的某一个
显然相邻两个数x+y的奇偶性肯定不同,那把为奇数的取个反
在求一下最大都是0/1的子矩阵,很显然悬线一下就可以了QAQ
BZOJ1058: [ZJOI2007]报表统计
一眼平衡树对吧QAQ
用stl水过QAQ
就是暴力覆盖就行了,不开long long见祖宗-70pts
显然stl对吧
\型对角线x-y为定值
/型对角线x+y为定值
x+y写成y-x,GG,-90pts
考虑前缀和的话
(M[i]-M[j])/(G[i]-G[j])= m/g
g*(M[i]-M[j]) = m*(G[i]-G[j])
gM[i]-mG[i] = gM[j]-mG[j]
发现左右形式都一样,设为t[i],那就map一下不就行了嘛QAQ
注意,第0位置 t[0]置为0,cnt[0]=1;
如果两个黑棋子在同一列,那么不管怎么操作,它两都会在同一列
如果在同一行,不管怎么操作,它两都会在同一行
所以就是判定是否有n个棋子x,y都不相同
这,就是二分图最大完全匹配对吧
f[x]:在x这棵子树里叶节点到根的最大距离
显然就是这个最大距离不可能再给他加距离对吧
应该把没到f[x]的变成它,也就是说把x这棵子树里所有叶节点到根的距离统一为f[x]