P2882 Face The Right Way - USACO07MAR
2016-11-07 10:51
197 查看
这道题没有一个比较详细的题解,我来提供一份。
首先我们可以知道,反转区间的顺序对结果没有影响,而且一个区间如果翻转两次以上是没有意义的,所以,问题就变成了求哪些区间需要反转。
我们枚举k。对于每一个k,我们设计一个calc函数来判断k的操作次数。
显然的,我们可以设计出一种方法,就是每一次都检查最左端,然后进行反转,很容易写出下面的calc函数。
int calc(int k) { int ans = 0; int i; for(i = 1; i + k - 1 <= N; i++) { if(f[i] == 1) { for(int j = i; j <= i + k - 1; j++) { f[j] = !f[j]; } ans++; } } for(i--; i <= N; i++) { if(f[i] == 1) return -1; } return ans; }
这样的检查方式复杂度为O(n2),再结合枚举k,总的复杂度是O(n3),这样的复杂度可以通过70%的数据,但还不够好。
我们来考虑怎么优化。显然的,我们没有必要去记录每一个的状态,我们只需要存储每一个区间是否反转过。所以,我们定义
f[i]为区间[i, i+k-1]是否反转。
这样,反转的复杂度就降到了O(1),总的复杂度就降到了O(n2),这样我们就可以AC这道题了。
对于实现上还有一个问题,就是怎么判断每一个格子的状态,这个问题我们留给读者思考。
下面贴上calc的代码。
int calc(int K) { memset(f, 0, sizeof(f)); int ans = 0; int sum = 0; for(int i = 0; i + K <= N; i++) { if((g[i] + sum) % 2 != 0) { ans++; f[i] = 1; } sum += f[i]; if(i - K + 1 >= 0) sum-=f[i-K+1]; } for(int i = N - K + 1; i < N; i++) { if((g[i] + sum) % 2 != 0) { return -1; } if(i-K+1 >= 0) { sum-=f[i-K+1]; } } return ans; }
如果有问题,可以私信。
相关文章推荐
- poj 3276 Face the right way
- POJ 3276 Face The Right Way(开关问题)
- bzoj1704/poj3276[Usaco2007 Mar]Face The Right Way自动转身机
- bzoj1704/poj3276[Usaco2007 Mar]Face The Right Way自动转身机
- POJ 3276 Face The Right Way
- POJ-3276 Face The Right Way
- poj3276 Face The Right Way
- Face The Right Way poj 3276 开关问题
- POJ 3276 Face The Right Way【开关问题】
- [bzoj1704][Usaco2007 Mar]Face The Right Way 自动转身机_贪心
- POJ 3276 Face The Right Way
- poj3276 Face The Right Way
- POJ 3276 Face The Right Way 笔记
- Poj 3276 Face The Right Way
- POJ 3276 Face The Right Way——开关问题
- poj3276 Face The Right Way 反转问题
- POJ 3276 Face The Right Way
- POJ_3276_Face The Right Way_区间反转问题
- POJ 3276 Face The Right Way 反转问题 常用技巧
- 【bzoj1704】[Usaco2007 Mar]Face The Right Way 自动转身机 贪心