题目:戳这里
题意:有n*m个点全为白色,q个圆,将q个圆内所有的点都染成黑色,问最后剩下多少白色的点。
解题思路:每一行当做一个扫描线,扫描所有的圆,记录每一行在圆中的点即可,O(n*q)。
附ac代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <string> 6 #include <cmath> 7 using namespace std; 8 const int maxn = 2e5 + 10; 9 struct nod 10 { 11 int x; 12 int y; 13 int r; 14 nod(){} 15 bool operator < (const nod & b) const 16 { 17 if(x == b.x) return y < b.y; 18 return x < b.x; 19 } 20 }nu[maxn],a[maxn]; 21 int main() 22 { 23 int t; 24 int n, m, q; 25 scanf("%d", &t); 26 while(t--) 27 { 28 int ans = 0; 29 scanf("%d %d %d", &n, &m, &q); 30 for(int i = 1; i <= q; ++i) 31 { 32 scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].r); 33 } 34 int len = 0; 35 for(int i = 0; i < n; ++i) 36 { 37 len = 0; 38 for(int j = 1; j <= q; ++j) 39 { 40 int u = a[j].r * a[j].r - (a[j].x - i) * (a[j].x - i); 41 if(u < 0) continue; 42 u = sqrt(u); 43 //printf("%d u ", u); 44 nu[++len].x = max(a[j].y - u, 0); 45 nu[len].y = min(a[j].y + u, m - 1); 46 //printf("%d len %d %d ", len, nu[len].x, nu[len].y); 47 } 48 if(len == 0) continue; 49 sort(nu + 1, nu + 1 + len); 50 int lt = nu[1].x, rt = nu[1].y; 51 for(int j = 2; j <= len; ++j) 52 { 53 if(nu[j].y < 0) continue; 54 if(nu[j].x >= m) break; 55 if(rt >= nu[j].x) 56 { 57 rt = max(rt,nu[j].y); 58 } 59 else 60 { 61 ans += rt - lt + 1; 62 //printf("%d i %d %d lt %d rt ", i, ans, lt, rt); 63 lt = nu[j].x; 64 rt = nu[j].y; 65 } 66 } 67 ans += rt - lt + 1; 68 //printf("%d i %d %d lt %d rt ", i, ans, lt, rt); 69 } 70 printf("%d ", n * m - ans); 71 } 72 return 0; 73 }