A(UVA12336)
题意:给一个n*m(n,m<=1e5)的棋盘,棋盘上有一些障碍点不能放棋子,现在要在棋盘上放4个棋子,满足A->B->C->D->A,其中走的规则是跳马字,问一共有多少种方案
分析:数学计算+hash
因为A、B、C、D可以顺时针、逆时针、随便以谁为起点放,所以对于一个确定的图形,一共有8种方案,所以问题就变成了寻找有多少个图形
容易想到用总的图形个数-障碍点占据的图形个数
先分析一共有多少种图形,一共有六种,一种是5*3格子里的直菱形,一种是3*5格子里的直菱形,还有4种分别是4*4格子中的4种情况
那么总的个数就是5*3矩阵的个数+3*5矩阵的个数+(4*4矩阵的个数)*4
然后再分析障碍点占据的图形个数
这很明显会出现共用的情况,最简单的方法就是记录下从一个障碍点出发的图形上有多少个障碍点,记录下ans[1],ans[2],ans[3],ans[4],那么ans=ans[1]+ans[2]/2+ans[3]/3+ans[4]/4
对于每个障碍点,枚举6种图形,并且枚举它在这种图形的四个顶点的哪个点(这里可以根据基础方向坐标不断顺时针旋转)
统计所到点是否是障碍点,就用hash吧,用set、map什么的会TLE
B
= =
C
=w=
D
QvQ
E
题意:将一个十进制数转成-2进制
分析:套路
当时我写的时候写的很复杂,是从高位逼近,后来网上找到了转负进制的通法
比如10进制要转-R进制,同样也是不断取模(-R),整除(-R),那么问题就是有的位上会出现负数,这不符合-R进制的数字局限
有个很巧妙的方法,就是给这个位置上的数+R,那么整个数字就改变了R*R^i=R^(i+1),那么第i+1位上的数字加上一个1即可(因为相邻位正负性恰好相反)
具体做的时候,不断取模-R,如果发现某位<0,给这位+R,给剩余整除的数+1即可
沃老师在讲题的时候是通过分析-2进制的奇偶性来解释这一过程的……
F(OpenJ_POJ C15C 北大2015校赛C题)
题意:n个点,m条边的无向图(n<=1e5,m<=2e5),有时间点1~k(k<=1e5),但是每条边在某个确定的时间点(每条边只有一个时间点)会断掉,特别的,有的边永远不会断。询问每个时间点,互相相连的点对有多少个
分析:cdq分治+可撤销并查集
题目求解的是互相相连的点对,本质是维护能够删除的并查集
有一种很好的离线分治做法,对时间进行分治[l,r]
对于每个中间点mid,先将[mid+1,r]这些时间点会断的边全部加入并查集,然后继续向左递归
直到[1,1],那么这个时候加入并查集中的正好是[2,k]的,那么[1,1]的答案就出来了
然后我们接下来希望得到[2,2]的答案,很关键的一点就是要把时间点为2的边全部删掉,我们可以惊奇地发现这些边是我们最后加入到并查集中的
一般来说,对于[l,r],先将[mid+1,r]中所有边加入并查集,再递归处理[l,mid],然后将[mid+1,r]中的边全部删掉、将[l,mid]中的边全部加入(因为这部分答案我们已经得到了),再递归处理[mid+1,r],这样我们删除的所有边都是刚刚加入并查集的边,所以如果将并查集的加边当作一个栈的话,我们就是不断弹出栈顶的边
这里并查集要求的可持久化仅仅是要求最近的上一次的信息
这种可撤销并查集的实现很简单,用按秩合并的并查集即可,入栈时记录入栈前两个点各自信息保存下来,出栈时候按照记录的值恢复即可
至于统计答案,合并的时候将两个即将连通的连通块的size相乘加到ans中,撤销时候减去
分析下复杂度,对于k个时间点信息,有logk层需要将其加入并查集,从并查集中撤销,因为是按秩合并的并查集,所以复杂度是logk,所以总的就是O(K*log^2(k))
这种按时间整体分治的cdq分治好神啊!就是处理完左边的,处理右边,考虑左边对右边的答案统计的影响。还涉及到可撤销的并查集,这题真神啊~~~~