摘要: 分析:首先要知道有递推公式dp[i] = Sigma(dp[j]),dp[i]表示第i个数结尾的完美子序列的个数,|a[i] - a[j]| i的[a[i] - d, a[i] + d]区间里面的数结尾的完美子序列个数也可以加进去,只要初始化都为0,正因为这样可以用树状数组对这种加法进行加速,只要先用二分查找出区间两端点对应在树状数组里面的下标。 1 #pragma warning(disable:4996) 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #define MOD 9901 9 ... 阅读全文
posted @ 2014-02-18 10:44 Hogg 阅读(320) 评论(0) 推荐(0) 编辑
摘要: 分析:一个最暴力的想法是把加入到集合S的数据一个个按顺序保存起来,然后每次查询的时候由后向前计算余数,如果遇到余数为0的,就直接把时间输出,否则就一直比较到最后找余数最小时间最晚的,这样查询的时间复杂度是n(当前S的元素个数)。另一个想法就是利用x、y的数据范围,建线段树表示[1,500000]这个区间,用来更新和查询任意[a,b]区间的最小值。因为[m*y,(m + 1)y - 1]内每个数除y的余数都是唯一的,而且被除数越小余数就越小,所以我们可以查询每个小区间的最小值,再比较应该取哪个时间就可以了。查询的时间复杂度为(maxN/y)*lg(maxN),可见y越大查询时间越短。但y很小时, 阅读全文
posted @ 2014-02-17 15:50 Hogg 阅读(222) 评论(0) 推荐(0) 编辑
摘要: 先将树DFS一次得到一个序列,按这个顺序把节点上的苹果数放到一个一维数组,每棵子树的苹果数就相当于数组对应的一段元素的和。这个数组我们用树状数组来维护就可以加快速度。 1 #include 2 #include 3 #pragma warning(disable:4996) 4 using namespace std; 5 int bit[100001], a[100001];//bit -- binary indexed tree 6 int lowBit(int x){ 7 return x & (-x); 8 } 9 void add(int idx, int size, i.. 阅读全文
posted @ 2013-12-15 00:31 Hogg 阅读(362) 评论(0) 推荐(0) 编辑
摘要: 这道题其实是挺简单的。首先很容易发现最多人用的颜色的人数如果大于n/2,就肯定不能让全部人都成功戴上两只不同颜色的手套。反过来想,如果这个人数小于等于n/2又如何呢?的确,这就能让全部人都能戴上两只不同颜色的手套(每个人都留一只自己原本的,再要别人的一只手套就可以了)。 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 struct Child{ 9 int color, num, mat;10 };11 bool partition_cmp(... 阅读全文
posted @ 2013-12-08 14:55 Hogg 阅读(347) 评论(0) 推荐(0) 编辑
摘要: 分析:首先我们要知道调用swap()函数的次数跟什么有关。可以观察发现在Insertion Sort里,当且仅当a[j](j∈[0,i)) > a[i]时会调用一次swap(),也就是说有多少个a[j](j∈[0,i)) > a[i]成立就会调用多少次swap()(因为a[i]前面的序列都是有序的),这个数目也叫逆序数。所以要使调用swap()的次数最少,就应该要使整个序列的总的逆序数最小。这时,我们可以枚举所有不同的两个位置对换之后的总逆序数来找最小的总逆序数。但枚举的时候我们需要知道a[i]与a[j]对换之后各自的逆序数以及对换之前的逆序数,记为b[i][j]、b[j][i]、 阅读全文
posted @ 2013-11-15 21:00 Hogg 阅读(479) 评论(0) 推荐(0) 编辑
摘要: 题意:有m个人,每人只有一张50元,还有n个人,每人只有一张100元,这些人排队买50元的电影票。售票处一开始没有钱,问要让这m+n个人全部顺利买票的排队方法有多少种。分析:把只有50元的人记为0,把只有100元的人记为1,问题等价于,m个0,n个1组成的序列中,由左向右累计,在任意一个位置的0的累计数都不少于1的累计数的序列有多少排列方式,结果再乘以m!n!(因为每个人都是不同的)。这道题有一个巧妙的解法:n=0时,答案显然是m!m=n的情况。m=6,n=6时,一个非法的序列例如,001101100011(6个0,6个1),把第一个使序列非法的1右面的每个位翻转,即变成00110111110 阅读全文
posted @ 2013-11-06 15:41 Hogg 阅读(472) 评论(0) 推荐(0) 编辑
摘要: 题意:解数独分析:完整的数独有四个充要条件:1.每个格子都有填数字2.每列都有1~9中的每个数字3.每行都有1~9中的每个数字4.每个9宫格都有1~9中的每个数字可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。在DFS里删除列的顺序为由左往右时TLE了,由右向左却AC,什么原因??? 1 #include 2 #include 3 int U... 阅读全文
posted @ 2013-08-30 10:36 Hogg 阅读(982) 评论(0) 推荐(0) 编辑
摘要: 题意:求01矩阵的精确覆盖。分析:本来想学习dancing links来解决数独问题,发现dancing links最初解决的问题是精确覆盖,于是就找到这道题来做了。这种NPC问题只能用DFS暴搜的情况下,很适合的一种优化方式就是用dancing links加速状态的改变,利用双向循环十字链表使元素的删除与恢复操作非常简便快捷。 1 #include 2 3 int U[102005],D[102005],L[102005],R[102005]; 4 int X[100005],Y[100005],H[1005],S[1005],ans[1005],len,M,N,sz; 5 ... 阅读全文
posted @ 2013-08-29 13:43 Hogg 阅读(558) 评论(0) 推荐(0) 编辑
摘要: 题意:由一个点走到另一个点,中间的点可以重复到达,但边只能经过一次,问T条边不重复的路径里,最长的边的最小值.分析:由于点是可以重用的,因此不必拆点.这道题有重边,而且重边都必须保留,因为点是可以重复走的.二分最长的边长,用最大流来验证. 1 #include 2 #include 3 #include 4 const int MAXN=205;//点数的最大值 5 const int MAXM=160005;//边数的最大值 6 const int INF=0x3fffffff; 7 8 struct Node 9 { 10 int from,to,next... 阅读全文
posted @ 2013-08-03 10:08 Hogg 阅读(299) 评论(0) 推荐(0) 编辑
摘要: 1 #include 2 #include 3 const int MAXN=250;//点数的最大值 4 const int MAXM=12500;//边数的最大值 5 const int INF=0x3fffffff; 6 7 struct Node 8 { 9 int from,to,next; 10 int cap; 11 }edge[MAXM]; 12 13 int tol; 14 int head[MAXN]; 15 int dep[MAXN]; 16 int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的... 阅读全文
posted @ 2013-08-01 23:26 Hogg 阅读(243) 评论(0) 推荐(0) 编辑