AtCoder Regular Contest 089 D - Checker
2018-01-27 17:02
585 查看
题目大意:
现有一个二维平面,并定义一个名词“ KK 单位块” ;“ K<4000
/span>K 单位块” 表示以 K×KK×K 的方格为单位,将二维平面涂成黑白相间的形式。如图就是一个“33 单位块” 涂成的二维平面:
现有 NN 个点,以及各点的期望颜色(‘B′‘B′ 表示黑色,′W′′W′ 表示白色)。问最多有几个点能被涂成所期望的颜色?
题目链接:
ARC089-D-Checker数据范围:
1≤N≤1051≤K≤10001≤N≤1051≤K≤10000≤xi,yi≤1090≤xi,yi≤109 且 i≠ji≠j 时 (xi,yi)≠(xj,yj)(xi,yi)≠(xj,yj)
解题思路:
如果一个点 (x,y)(x,y) 的期望颜色是白色,相当于点 (x,y+K)(x,y+K) 的期望颜色是黑色 (其实(x+K,y)(x+K,y) 也是黑色,这里只为了说明思路);那么 (x,y,′W′)(x,y,′W′) 就可以转化为 (x,y+k,′B′)(x,y+k,′B′) 。如果一个点 (x,y)(x,y) 的期望色是黑色,点 (x+2K,y+2K)(x+2K,y+2K) 的颜色是一样的,那么 (x,y,′B′)(x,y,′B′) 和 (x%2K,y%2K,′B′)(x%2K,y%2K,′B′) 是等价的。
通过这两步转化之后,就可以在 2K×2K2K×2K 的平面中求解了。如果通过枚举左下角、依次 check ,复杂度是不够的。用 矩阵前缀和 优化一下,O(1)O(1) 回答某个矩阵和,复杂度就降为了 O(K2+N)O(K2+N) 。
太菜了!
因为涂刷方案有很多种,所以开始还在想怎么计算那些“单位块零散”的方案;后来看了大S们的代码,搞个 4K×4K4K×4K 的数组不就可以了!就像以前一圈儿数做开头,数组开 22 倍一样。
mod 完之后坐标范围为 [0,2K)[0,2K) ,在查询坐标含0的矩阵的,因处理不当RE了一发,改完之后代码已经100+了;后来看大S们的代码,哈!居然用后缀和这种骚操作,改完之后代码80+ 。(贴出后缀和代码)
AC代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> using namespace std; typedef long long LL; const int inf = 1 << 30; const LL INF = 1LL << 60; const int MaxN = 100005; const int MaxM = 1000; int n, k; int M; struct Point { int x, y; char c; Point () {} Point (int _x, int _y, char _c) { x = _x; y = _y; c = _c; } }PP[MaxN + 5]; int sum[4 * MaxM + 5][4 * MaxM + 5]; void init() { M = 2 * k; memset(sum, 0, sizeof(sum)); for(int i = 1; i <= n; i++) scanf("%d %d %c", &PP[i].x, &PP[i].y, &PP[i].c); } int cal(int lx, int ly, int ux, int uy) { //计算某个矩阵和 return sum[lx][ly] - sum[lx][uy + 1] - sum[ux + 1][ly] + sum[ux + 1][uy + 1]; } void change() { for(int i = 1; i <= n; i++) { //转化 if(PP[i].c == 'B') { int tx = PP[i].x % M; int ty = PP[i].y % M; sum[tx][ty]++; } else if(PP[i].c == 'W') { int tx = (PP[i].x) % M; int ty = (PP[i].y + k) % M; sum[tx][ty]++; } } for(int i = 0; i < M; i++) { //扩充矩阵 for(int j = 0; j < M; j++) { sum[i + M][j] = sum[i][j]; sum[i][j + M] = sum[i][j]; sum[i + M][j + M] = sum[i][j]; } } for(int i = 2 * M - 1; i >= 0; i--) { //计算后缀和 for(int j = 2 * M - 1; j >= 0; j--) { sum[i][j] = sum[i][j] + sum[i + 1][j] + sum[i][j + 1] - sum[i + 1][j + 1]; } } } void solve() { int best = 0; for(int i = 0; i < M; i++) { for(int j = 0; j < M; j++) { int tmp = cal(i, j, i + k - 1, j + k - 1) + cal(i + k, j + k, i + M - 1, j + M - 1); best = max(best, tmp); } } printf("%d\n", best); } int main() { while(scanf("%d %d", &n, &k) != EOF) { init(); change(); solve(); } return 0; }
相关文章推荐
- AtCoder Regular Contest 089 D Checker
- AtCoder Regular Contest 089 D - Checker 思维题、点的转移、二维前缀和
- AtCoder Regular Contest 089 C - Traveling
- AtCoder Regular Contest 089
- AtCoder Regular Contest 089 E-GraphXY-构造题
- AtCoder Regular Contest 071 F
- atcoder AtCoder Regular Contest 084 D - Small Multiple 最短路
- AtCoder Regular Contest 076
- AtCoder Regular Contest 066 E - Addition and Subtraction Hard 动态规划
- AtCoder Regular Contest 078
- AtCoder Regular Contest 090 D People on a Line【dfs + bfs】
- [AtCoder Regular Contest 064] F: Rotated Palindrome (arc064F)
- AtCoder Regular Contest D - Remainder Reminder 取余问题
- AtCoder Regular Contest 092 C - 2D Plane 2N Points 贪心 匈牙利算法模板
- AtCoder Regular Contest 080 F - Prime Flip 二分图匹配+哥德巴赫猜想
- AtCoder Regular Contest 058 C-こだわり者いろはちゃん / Iroha's Obsession
- AtCoder Regular Contest 070 D - No Need 想法:利用单调性二分+bitset优化
- Atcoder Regular contest 085F NRE 线段树+DP
- 从AtCoder Regular Contest 077D: 11 中学习逆元的线性求法
- AtCoder Regular Contest 077 E - guruguru