[BIT][思维][反证][差分求极值] codeforces1030F Putting Boxes Together

题目:http://codeforces.com/problemset/problem/1030/F

这个题最主要的是自己没有想出来怎么求出那个“不动的点”,因为其实整体的cost用k去表示出来是很困难的,求出来也无法发现其极值点。但是如果考虑差分就会比较好做,很容易发现当当前设的k点变成k+1时,cost变化了(S(l,k)-S(k+1,r))*(p[k+1]-p[k]),其中S(l,r)=Σw[i](l<=i<=r)。这样的话很明显当且仅当S(l,k)S(k+1,r)S(l,k)≤S(k+1,r)时k+1比k更优。所以我们只要找到最小的k使得S(l,k)>=S(l,r)/2就行了!

然后是对于一个[l,r]对求出k之后,如何快速的求出其cost。

对于i(l,k)i∈(l,k) 代价是(pkpi(ki))wi(l<=i<=k)
对于i(k,r)i∈(k,r) 代价是(pipl(ik))wi(k<=i<=r)

把pi-i看成一个整体,记为ai,就可以得到cost=(akai)wi(l<=i<=k)+(aial)wi(k<=i<=r)

展开整理就可以得到cost=ak*(S(l,k)-S(k,r))-(Σwi*ai(l<=i<=k)-Σwi*ai(k<=i<=r))。这样的话用一个BIT快速求S(l,r),另一个BIT快速求Σwi*ai就可以了。

wa点的话,发现了一个以前没有注意到的bug,那就是我每次判断都是if(x>mod)x%=mod;但是忽然意识到在有减法的运算中,还有一种下越界的可能性,所以应该是if(x>mod||x<-mod)x%=mod; 继续阅读“[BIT][思维][反证][差分求极值] codeforces1030F Putting Boxes Together”

[暴力][分块][思维] CF 1030E Vasya and Good Sequences

题意如果一个序列中[l,r]里面的数,可以通过调整每个数的二进制位使得其异或和为0,那么这个[l,r]对就是good的,然后求有多少个这种[l,r]对,序列长度3e5。

一开始想dp,又是分位又是奇偶的,始终没搞出来。看了官方题解才发现判定一个[l,r]段是否为goog的充分必要条件只有两个,首先设bi为ai的二进制表示中的1的个数,则充要条件为:

① Σbi(l<=i<=r) 为偶数

② max(bi)<=Σbi(i!=index(max(bi)) 继续阅读“[暴力][分块][思维] CF 1030E Vasya and Good Sequences”

[几何][数学][思维] CF 1030D Vasya and Triangle

题意:给定n,m,k,要求在横坐标小于n纵坐标小于m的整点中找到一个三角形使得三角形面积为 n*m/k。一开始一直纠结于存在性。首先可以证明如果2*n*m%k!=0那么一定是NO。当满足这一条件的时候,可以把n*m/k上下拆分,把k拆成gcd(n,k)*(k/gcd(n,k)),然后上下约分就可得到一组ab,这时候如果后者和m不能完全约分说明分母里会剩下一个2(因为分子上*2是可以完全约分的),这时候ab就是答案的两条边因为不需要除2了。如果能完全约分则还需要在分子的a或者b上乘一个2,哪个小乘哪个就好了。为什么乘2不会超过原来的n或者m?因为我们这时候一定是n*m%k==0,而且题中k>=2,所以n和m至少有一个可以除一个2。
感觉做的时候问题主要在于无法验证正确性,但是后来发现k>=2这个条件是极其重要的。。。。没有这个条件就可能无解了 继续阅读“[几何][数学][思维] CF 1030D Vasya and Triangle”

[CF][区间标记方法][暴力] codeforces 1028C Rectangles

比赛时候wa到哭,后来发现优化错了,把优化去掉玄学AC(这可是三个for啊这复杂度)

后来想一下,之所以能玄学过,就是因为题目保证了一定有解,如果无解的话那三个for还真有可能跑一遍,不说三个了两个跑一遍都够呛。。

我这里的玄学算法就是,对横纵坐标分别标记,当一个点在纵方向上被至少n-1个举行覆盖的时候才考虑这个横坐标,然后在这个横坐标上的所有纵坐标,也只有当被至少n-1个覆盖到的时候才考虑它,当然这只是必要条件而不是充分条件,然后对于一个要考虑的点遍历所有矩形(没错就是这么暴力)如果有超过1个没覆盖到这个点就退出直接不考虑。。。就这么超级暴力+剪枝,玄学过了cf的所有数据,emmm 继续阅读“[CF][区间标记方法][暴力] codeforces 1028C Rectangles”

[CF][贪心][枚举][思维] CF1019A

http://codeforces.com/problemset/problem/1019/A

今天想起来这坑还没填。心情差.jpg

当时比赛想了一个小时dp,然后在最后10min意识到可以枚举最后所需要的人数然后贪心。。可是已经没时间来实现了,然后就果断地凉了。今天直接补了

一开始纠结,主要在于,这个决策既得考虑人数又得考虑钱,有点像背包,就很不好操作。但是实际上,n范围只有3000,所以完全可以枚举人数,在这个固定的条件下去考虑对于一特定的人数x需要多少钱,就很容易了:每次先把人数大于等于x的减到x-1,把减去的人加到党派1的支持者数量里,这个过程中挑最小的那些累计起来。在做完这些工作后就是看有没有达到人数x,如果达到了/超过了就说明行了,虽然超过的话就不是正好x但是我们只关心钱数的最小值,如果没有达到,那么还需要从剩下的所有人里从小到大累计够人数才可以。

我这里只排序1次,然后每次设置used数组表示一个人是不是在第一步里用过了。算是n^2复杂度吧。当然这个题数据貌似很水怎么都能过。。

实现的话还有一个问题就是按照我的写法遇到p为1的时候是不能设置used的,因为这个其实是针对于党派1之外的来说的。。。因为这个wa了一发。 继续阅读“[CF][贪心][枚举][思维] CF1019A”