BZOJ 1227 [SDOI2009]虔诚的墓主人 - 扫描线
Solution
离散化 扫描线, 并用 $rest[i]$ 和 $cnt[i]$ 记录 第$i$列 总共有 $cnt[i]$棵常青树, 还有$rest[i]$ 没有被扫描到。
那么 第$i$ 列的方案数 为 $C(rest[i], k) * C(cnt[i]-rest[i], k)$。 乘上行上的方案数 并加入答案。
需要注意组合数要预处理, 我直接算发现$k > 2$就会WA。
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #define rd read() 6 #define R register 7 using namespace std; 8 9 const int N = 2e5 + 5; 10 11 int cnt[N], sum[N], n, r, l, k, rest[N]; 12 int vis[11], ans; 13 int tot_x, tot_y, X[N], Y[N], c[N][15]; 14 15 struct node { 16 int x, y; 17 }pt[N]; 18 19 vector<node> q[N]; 20 21 inline int read() { 22 R int X = 0, p = 1; char c = getchar(); 23 for (; c > '9' || c < '0'; c = getchar()) 24 if (c == '-') p = -1; 25 for (; c >= '0' && c <= '9'; c = getchar()) 26 X = X * 10 + c - '0'; 27 return X * p; 28 } 29 30 inline int lowbit(int x) { 31 return x & -x; 32 } 33 34 inline void add(R int x, int d) { 35 for (;x <= tot_x; x += lowbit(x)) 36 sum[x] += d; 37 } 38 39 inline int query(R int x) { 40 int re = 0; 41 for (; x; x -= lowbit(x)) 42 re += sum[x]; 43 return re; 44 } 45 46 inline int fd_x(R int x) { 47 return lower_bound(X + 1, X + 1 + tot_x, x) - X; 48 } 49 50 inline int fd_y(R int y) { 51 return lower_bound(Y + 1, Y + 1 + tot_y, y) - Y; 52 } 53 54 inline int cmp(const node &A, const node &B) { 55 return A.y == B.y ? A.x < B.x : A.y < B.y; 56 } 57 58 inline int C(int x) { 59 return c[x][k]; 60 } 61 62 int work(int x) { 63 int len = q[x].size(), re = 0; 64 for (R int j = k - 1; j <= len - k - 1; ++j) { 65 int L = q[x][j].x, r = q[x][j + 1].x; 66 int tmp = query(r - 1) - query(L); 67 re += tmp * C(j + 1) * C(len - j - 1); 68 } 69 for (R int j = 0; j < len; ++j) { 70 int tmp = C(rest[q[x][j].x]) * C(cnt[q[x][j].x] - rest[q[x][j].x]); 71 add(q[x][j].x, -tmp); 72 rest[q[x][j].x]--; 73 tmp = C(rest[q[x][j].x]) * C(cnt[q[x][j].x] - rest[q[x][j].x]); 74 add(q[x][j].x, tmp); 75 } 76 return re; 77 } 78 79 void init() { 80 c[0][0] = 1; 81 for (int i = 1; i <= n; ++i) { 82 c[i][0] = 1; 83 for (int j = 1; j <= min(k, i); ++j) 84 c[i][j] = c[i - 1][j - 1] + c[i - 1][j]; 85 } 86 } 87 88 int main() 89 { 90 r = rd, l = rd; n = rd; 91 for (R int i = 1; i <= n; ++i) { 92 pt[i].x = rd, pt[i].y = rd; 93 X[++tot_x] = pt[i].x; 94 Y[++tot_y] = pt[i].y; 95 } 96 k = rd; 97 init(); 98 sort(X + 1, X + 1 + tot_x); 99 sort(Y + 1, Y + 1 + tot_y); 100 tot_x = unique(X + 1, X + 1 + tot_x) - X - 1; 101 tot_y = unique(Y + 1, Y + 1 + tot_y) - Y - 1; 102 sort(pt + 1, pt + 1 + n, cmp); 103 for (R int i = 1; i <= n; ++i) { 104 pt[i].x = fd_x(pt[i].x); 105 pt[i].y = fd_y(pt[i].y); 106 cnt[pt[i].x]++; 107 q[pt[i].y].push_back(pt[i]); 108 } 109 for (R int i = 1; i <= tot_x; ++i) 110 rest[i] = cnt[i]; 111 for (R int i = 1; i <= tot_y; ++i) 112 ans += work(i); 113 printf("%d\n", ans & 0x7fffffff); 114 }