【技巧总结】——关于不知道放到哪里的小技巧

折半搜索

当看到n非常小的时候,一般是(25~40),想暴力但是会T,这时候就可以想一想是否需要折半搜索

主要步骤有2个:
1.搜前一半,存答案
2.搜后一半,得到的结果和前一半去匹配

一般来说搜索只需要最普通的dfs即可,而存答案多和stl有关

经典例题:
L i g h t    s w i t c h e s Light\; switches Lightswitches(如果对半分容易T,那么预处理的时候多处理一点,处理20个,剩下在询问的时候处理即可)
X o r − P a t h s Xor-Paths XorPaths(显然在对角线处分开,这里处理的时候要记一下:当 x + y = = ( n + m ) / 2 + 1 x+y==(n+m)/2+1 x+y==(n+m)/2+1的时候, ( x , y ) (x,y) (x,y)就是对角线上的点了)
M a x i m u m    S u b s e q u e n c e Maximum \;Subsequence MaximumSubsequence(首先先把所有数字对m取模,然后求出前一半所有可能的和,后一半所有可能的和,设前一半的一个值为x,则在后一半里找比m-x小的第一个数即可)
L i z a r d    E r a : B e g i n n i n g Lizard \;Era: Beginning LizardEra:Beginning(枚举每个工作要分给哪些人,并用三进制状压记录方案就ok了,但是注意,在输出方案的时候,有最后一位对应的就是0,所以直接while(x)是不对的,应该给出明确的循环次数)

分治

类似于线段树的操作,处理一个区间的时候,把他分成两部分,每部分再按同样的方式进行处理(但是感觉没啥特征)
O p t i m a l    I n s e r t i o n Optimal\;Insertion OptimalInsertion(首先把b排序,能保证,对于b来说,贡献是0,逆序对最小,接着考虑b插入的顺序,找到b[mid],判断哪里逆序对最少,插进去后,a,b两个区间都被分成了两部分。mid前的数只能再往前面插,这样处理,时间复杂度就变成log了)
T h e    N u m b e r    o f    S u b p e r m u t a t i o n s The\;Number \;of \;Subpermutations TheNumberofSubpermutations(求排列的个数。可以从整段区间的最大值写起。找到最大值,这个可能的排列的长度就确定了,剩下的就是判断是否合法。当这个最大值处理完之后,剩下的排列都不能包含它了,所以就把区间分成两部分,然后重复操作。)
(但是判断是否合法的过程又很费时间,所以我用一个数组wz,记录有相同的值最靠近它出现的位置,比如1 2 2 1,的数组就是 0 0 2 2。枚举端点,如果wz[r]<l,说明在这一段区间内是没有相同的数字的,又因为我们当前考虑的是这段区间的最大值,所以这段区间内的数都是<=这个数,且不重复的,因此构成了一个排列)这点技巧可以掌握一下

0,1,-1转化

在求方案,可行性,反正就是和取值没有什么太大关系的时候,可以用0,1,-1代替原数,这样处理起来就会非常方便

经典例题:

T e l e p h o n e L i n e s Telephone Lines TelephoneLines(二分+最短路)(判断的时候,可以选取适当的参考,用0,1,-1代替原数,这样就可以用最后求出来的结果 O ( 1 ) O(1) O(1)判断是否合法了)
例: c o e x i t coexit coexit(把0改成-1,进行前缀和操作)
M i l k V i s i t s S Milk Visits S MilkVisitsS(这是一道lca的题,但是也是用01求答案,而且是我根本没看题解,自己码出来的(不容易啊),所以值得放上来)
整理书架(线段树+ -1,1标记)
冒泡排序(和上面竟然是一个思想!考的时候完全想不起来)
【bzoj3697】采药人的路径(把0变成-1,满足阴阳平衡只需要路径和为0就好了)

模型转换

E x t e n d i n g    S e t    o f    P o i n t s Extending\;Set\;of\;Points ExtendingSetofPoints

原题:在一个网格图中,如果(a,b),(a,y),(x,b)存在于集合中,那么(x,y)自动加入,直到加不下去,每次进行加点,删点操作,求每次的集合大小

转化:有两列数,一列为横坐标,一列为从坐标,把(a,b)看成a->b的边,若存在边(a,b),(a,y),(x,b),那么(x,y)自动连边,求总边数。可以发现,每次a向对面连的所有点,都会和b向对面连的所有点连边,设左边总点数为L,右边为R,那么答案就是L*R

摆棋子

原题:n*m的网格上,每个格子只能放一个棋子,有些不能放,每行每列都有一个限制,至少放那么多棋子,求最小需要的棋子数

转化:建立网络流模型
先把问题反转,求最多能省下多少个位置不放棋子,最后减一下即可
将每一行,每一列变成n+m个点,源点向表示行的点连边,容量为(每行空着的数量-需要的棋子数),若点(i,j)能放棋子,那么i向j+n连容量为1的边,列向汇点连边(同行),跑一遍最大流即可

图腾

原题:在 k 维空间中,如果 k+1 个整点 A0,A1,…,Ak 满足:
A0 的每一维坐标都是偶数
对于任意 0≤i<j≤k 都有 Ai 与 Aj 的欧几里得距离为 j − i \sqrt{j-i} ji
就称这 k+1 个点构成图腾。
现有 n 个整点 P1,P2,…,Pn ,你希望删去其中一些点使得剩余的点中任何 k+1 个都不构成图腾,问最少删多少点。

转化:建立最小割模型
题目可以发现,在一个图腾内,相邻的两个点一定是k位中只有一位差了1,所以A0一定都是偶数,那么Ak一定都是奇数。
我们对于每一个点,都去找和他只有一位差1的,连一条容量为maxx的边,源点向符合起点条件的连容量为maxx边,符合终点条件的向汇点连容量为maxx边,而对于每一个点,我们进行拆点,中间流量为1,表示切断这条边的代价是1,其实也就相当于删了这个点,然后求最小割就行了

D Z Y    L o v e s    C h i n e s e    I I DZY \;Loves\; Chinese\; II DZYLovesChineseII

原题:给一个图,每次删k条边(每次询问独立),问删完之后是否联通

转化:利用线性基性质解答
先随便找出一棵树,给树边赋上随机权值(随机的时候尽量大),然后非树边的权值等于两端点树上权值的异或和,把删除的边的权值尝试插入线性基,如果失败,表示把这个环都删了,那么就不连通了

正难则反

经典例题:
F a r m    U p d a t e s    G Farm\; Updates\;G FarmUpdatesG(正着做是把连通块断开,反着就变成不断合并联通块了,并查集的操作)
旅行路线(将图反过来就变成一棵树了)

对象转化

将计算有多少个,转化成当前这个对总答案的贡献是多少
经典例题:
m a t r i x matrix matrix

求x为次大值的最大区间

这样的最大区间有两个,一个是(左边第二个大于它的,右边第一个大于它的),另一个是(左边第一个大于它的,右边第二个大于它的),两个都是开区间。
此时可以用链表来解决,用 p e r , n x t per,nxt per,nxt表示左边第一个比他大的位置,右边第一个比他大的位置,刚开始赋成 i − 1 , i + 1 i-1,i+1 i1,i+1,然后把值排个序,按照顺序删除元素,同时查找,那么比它小的数都被删了, p r e , n x t pre,nxt pre,nxt自然会进行一些移动得到的这个结果就是要找的了,这么说可能有些模糊,意会一下
经典例题:
A l o Alo Alo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值