[Poj]3276——数学优化
[题目大意]
- 给定N只牛的朝向(向前或是向后),每次操作可以改变任意位置连续的K只牛的朝向。求一个最小的K使得将所有牛的朝向都变为向前的所需操作的次数最少
[分析题解]
- 直观的想法是枚举每一个K,然后计算所需的次数,取最小值。
- 计算所需的次数也非常的简单。从左向右扫描,每当遇到一个向后的牛就把他以及其后面的K-1头牛一起反向,最后判断合法性。这样的正确性是显然的,因为扫过去的牛如果现在不将其变为向前,以后也不能再将其变为向前了。
- 但是这样做的复杂度=O(n)的枚举*接近O(n^2)的计算=O(n^3)=TLE
- 尝试着优化
- 考虑优化计算部分。我们不去将牛反向,而是标记其被覆盖的次数。这样只要保证所有的向后都被覆盖了奇数次,所有向前的被覆盖了偶数次就可以了。这样就涉及到区间+1和查看一个点被覆盖的情况,用树状数组可以维护这两个操作,复杂度为O(logN)。这样计算的复杂度降为O(NlogN)。总的复杂度降为O(n^2LogN)。不过这样还不够...依然会超时
- 这样的话,考虑一下,在将一列牛取反的时候,有什么是不变的?
- 这些牛之间的关系是不变的!
- 这样就有一个巧妙的转化了,用F[I]表示第I头牛与前一头牛的关系,0代表方向相同,1代表方向不同,然后在整个队列前设置一个向前的牛,那么问题就转化为将一列数变为0,即都与第一头牛方向相同即可。然后我们考虑取反操作,因为中间的牛关系是不变的,所以不用管,变得只有第一头牛和队列最后一头牛的后一头牛,这样取反操作就是O(1)的。计算操作变为O(n),总的复杂度降为O(n^2)。这样就能够过掉了。
- 更深一步的优化我还没有考虑出来,不过应该是在K之间的关系或是各个1之间的关系之间做文章。才疏学浅,不能发现。
[个人代码]None
[相关链接]
[启发总结]
- 这道题的优化过程挺厉害的,循序渐进,这才是一个正常的思维过程。我觉得提高很大。
——————————————————————————————————————
你说,我们的存在,永不消逝。对吧?
如果,我们都在努力创造了存在。我们,会幸福的。对吧?