摘要: 1 /* 2 题意:给你n*m的棋盘,有些棋盘被一些矩形覆盖,求放进一个长为M,宽为1的矩形的方案数 3 4 离散,线段树 +扫描线 5 分析:最直接得想法,对于每一层统计空白连续的长度然后统计放的方案数,不过编程复杂度有点高 6 要分别记录下每个区间左边连续最长空白长度和右边最长连续空白长度, 7 然后count[rt]=count[r<<1]+count[rt<<1|1]+{跨两段的个数} 8 9 一个好想法:当以y为分层标准时,统计竖着放的方案数,那么把每个矩形都向下延伸M-1个单位, 10 那么剩下的每一个空位都对应一种方法,直接矩形并求面积就好,问题得到转.. 阅读全文
posted @ 2013-05-26 12:05 Rabbit_hair 阅读(335) 评论(0) 推荐(0)
摘要: 1 /*zoj2112 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 2 动态 kth 3 每一棵线段树是维护每一个序列前缀的值在任意区间的个数, 4 如果还是按照静态的来做的话,那么每一次修改都要遍历O(n)棵树, 5 时间就是O(2*M*nlogn)->TLE 6 考虑到前缀和,我们通过树状数组来优化,即树状数组套主席树, 7 每个节点都对应一棵主席树,那么修改操作就只要修改logn棵树, 8 o(nlognlogn+Mlognlogn)时间是可以的, 9 但是直接建树要nlogn*l... 阅读全文
posted @ 2013-05-24 10:00 Rabbit_hair 阅读(5407) 评论(0) 推荐(0)
摘要: 1 /* 2 主席树:对于序列的每一个前缀建一棵以序列里的值为下标的线段树(所以要先离散化), 3 记录该前缀序列里出现的值的次数; 4 记离散后的标记为1~n; (下面值直接用1~n代替;) 5 对于区间[x,y]的第k大的值,那么从root[x-1],root[y]开始, 6 t=root[y].[1,mid]-root[x-1].[1,mid] ,t表示区间[x,y]内值在[1,mid]的个数 7 先判断t是否大于K,如果t大于k,那么说明在区间[x,y]内存在[1,mid]的数的个数大于k, 8 也就是第k大的值在[1,mid]中,否则在[mid+1,r]中; 9 10 这样我们... 阅读全文
posted @ 2013-05-23 12:32 Rabbit_hair 阅读(5139) 评论(0) 推荐(3)
摘要: 1 /* 2 题意:给你n的序列求最长子序列,该序列里|a[i]-a[i-1]|<=d 3 4 分析:O(n^2)的DP很容易想到,那么显然优化也很容易想到 5 用线段树维护区间最大值, 6 设dp[i]表示以数值为i结尾的最长符合要求序列, 7 对于a[i],询问值为[a[i]-d,a[i]+d]的最大值,然后在单点更新; 8 注意要先离散; 9 10 11 12 */13 14 #include<cstdio>15 #include<cstring>16 #include<cstdlib>17 #include<iostream>18 阅读全文
posted @ 2013-05-22 22:10 Rabbit_hair 阅读(304) 评论(0) 推荐(0)
摘要: 1 /* 2 题意:n天,第i天可以获得的值为vi,如果获得第i天的值,那么下一次能获得的值 3 只能在[i+x[i],i+y[i]-1]天中取,为最大能获得多少值; 4 5 分析:直接DP,每次维护经过前i-1天第i天能可以获得的最大值,用线段树维护就要同时记录下区间的最大最小值; 6 表示区间内的可能获得最大值的最大值和最小值; 7 另一种DP的思路,dp[i]表示选了第i天,最终能获得的最大值,那么dp[i]=v[i]+max(dp[i+x[i]],dp[i+y[i]-1]); 8 直接用线段树维护区间最大值就可以了; 9 10 */11 #include<cstdio>12 阅读全文
posted @ 2013-05-22 16:02 Rabbit_hair 阅读(167) 评论(0) 推荐(0)
摘要: 1 /* 2 题意:n个数的序列,m个询问,每次询问给你区间[l,r]问是否区间内有两个相同的数; 3 如果没有输出OK,有的话输出最右边满足的数的值; 4 5 分析:从左到右扫描一遍,给每个数记录它左边最近的相同数的标号, 6 那么区间[l,r]最大的标号如果还小于l那么就不存在相同的数; 7 用线段树维护,顺便记录下该数的下标; 8 9 10 */11 #include<cstdio>12 #include<cstring>13 #include<cstdlib>14 #include<iostream>15 #include<cmat 阅读全文
posted @ 2013-05-21 22:12 Rabbit_hair 阅读(256) 评论(0) 推荐(0)
摘要: 1 /* 2 题意:给n个数,m个操作,每次把区间[l,r]的数用它们的平均值替代, 3 如果平均值不是整数,且当前n个数的和小于原先的和就向上round,不然就向下round; 4 5 分析:简单线段区间更新; 6 7 trick:关于正数和负数的整除问题,正数整除是自动向下取整的,但负数是向上取整的 8 即13/3=4.3 ->4 但-13/3=-4.3 ->-4 9 10 */ 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostr 阅读全文
posted @ 2013-05-21 21:31 Rabbit_hair 阅读(252) 评论(0) 推荐(0)
摘要: 1 /* 2 题意: 中文题 3 4 分析:就是区间覆盖,然后求最前连续长度为len的0串或01串的起始位置; 5 conl[rt][0]表示区间从左开始最长0串长度, 6 conr[rt][0]表示区间从右开始最长0串长度; 7 conl[rt][1]表示区间从左开始最长01串长度, 8 conr[rt][1]表示区间从右开始最长01串长度; 9 然后就是模拟; 10 11 */ 12 #include<cstdio> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm&g 阅读全文
posted @ 2013-05-18 21:32 Rabbit_hair 阅读(354) 评论(0) 推荐(0)
摘要: 1 /* 2 题意:售货员每隔w分钟就会睡觉,如果售货员睡着了那么顾客会叫醒她但是不会买东西, 3 有n个客人会不同时间来,并且售货员卖给第i的客人的价格为p[i],并且售货员会在第k次卖 4 出1+(k-1)%3个面包,求问最小的w使平均每次卖出的面包的价格最大即总收入/卖的次数; 5 6 分析:如果w小于最小的时间间隔,那么售货员不会卖出一个面包显然不是最优的, 7 当w>某一个时间间隔,那么会买面包的顾客都是时间间隔小于w的, 8 显然最后答案肯定是某一个顾客的时间间隔,枚举要O(n^2),肯定超时; 9 我们知道当w按顾客时间间隔递增,那么前面会买面包的顾客后面还... 阅读全文
posted @ 2013-05-18 14:22 Rabbit_hair 阅读(261) 评论(0) 推荐(0)
摘要: 1 /* 2 这一题有点坑,刚开始的时候就想着对于每一个y分成n/y段来统计, 3 但是发现y很小的时候效率很糟糕,然后就想不出了,以为会有什么超绝的想法 4 或者结合数论来搞,然后就是糟糕的百度题解!! 5 发现y很小的时候直接暴力,这效率能行么,对于算时间复杂度我是完全不会的, 6 暴力时间O(n),用线段树时间 O(N/Y*log(N));只能说y取10^3的时候两者时间差不多, 7 最后感觉是卡过的,但又因为有插入操作,如果都是询问的或者都是插入的话时间大概为10^8 8 然后如果有一半插入的话,时间就更短,所以应该可以吧; 9 10 */ 11 12 13... 阅读全文
posted @ 2013-05-18 00:22 Rabbit_hair 阅读(353) 评论(0) 推荐(0)