bzoj 1227 SDOI2009 虔诚的墓主人
思路还是蛮清晰的
ask:
x = t[nowright-1] - t[nowleft]
get_ans:
ans += C(l[nowleft],k) * C(r[nowright],k) * x
update:
t[i] = t[i] - C(up[i],k) * C(down[i],k) + C(up[i]-1,k) * C(down[i]+1,k)
sort:
y first
x second
组合数的递推公式都忘了……
C (i, j) = C (i-1, j) + C (i-1, j-1)
这道题模比较大,乘的时候要注意不爆 long long
上代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <iostream> #include <cmath> #include <map> #define yu 2147483648LL #define N 100100 using namespace std; struct sss { int x, y; }dian[N]; int n, K, linenum = 0; long long ans = 0, t[N] = {0}; map <int, int> qx, qy, rank; int up[N], down[N], fan[N]; long long C[N][11] = {0}; bool cmp(sss a, sss b) { return a.y == b.y ? a.x < b.x : a.y < b.y; } int lowbit(int x) { return x & -x; } void add(int now, int addnum) { addnum %= yu; while (now <= linenum) { t[now] += addnum; while (t[now] > yu) t[now] -= yu; now += lowbit(now); } } long long ask(int now) { long long zan = 0; while (now) { zan += t[now]; while (zan > yu) zan -= yu; now -= lowbit(now); } return zan%yu; } void makeC() { C[0][0] = 1; for (int i = 1; i <= n; ++i) { C[i][0] = 1; for (int j = 1; j <= min(i, K); ++j) { C[i][j] = C[i-1][j-1] + C[i-1][j]; while (C[i][j] > yu) C[i][j] -= yu; } } } void beforework() { int xz[N]; makeC(); for (int i = 1; i <= n; ++i) xz[i] = dian[i].x; sort(xz+1, xz+1+n); xz[0] = -1; for (int i = 1; i <= n; ++i) if (xz[i] != xz[i-1]) { rank[xz[i]] = ++linenum; fan[linenum] = xz[i]; } for (int i = 1; i <= linenum; ++i) { up[i] = qx[fan[i]]; down[i] = 0; } } void get_ans() { int ybefore = -1, l, r; long long x; int i = 1; while (i <= n) { if (dian[i].y != ybefore) { l = 1; r = qy[dian[i].y]-1; ybefore = dian[i].y; int d = rank[dian[i].x]; add(d, C[up[d]-1][K] * C[down[d]+1][K] - C[up[d]][K] * C[down[d]][K]); up[d]--; down[d]++; } else { x = ask(rank[dian[i].x]-1) - ask(rank[dian[i-1].x]); if (x < 0) x += yu; ans += (((x * C[l][K])%yu) * C[r][K])%yu; l += 1; r -= 1; while (ans > yu) ans -= yu; int d = rank[dian[i].x]; add(d, C[up[d]-1][K] * C[down[d]+1][K] - C[up[d]][K] * C[down[d]][K]); up[d]--; down[d]++; } i++; } } int main() { scanf("%d%d%d", &n, &n, &n); for (int i = 1; i <= n; ++i) { scanf("%d%d", &dian[i].x, &dian[i].y); qx[dian[i].x] ++; qy[dian[i].y] ++; } scanf("%d", &K); sort(dian+1, dian+1+n, cmp); beforework(); get_ans(); printf("%I64d\n", ans%yu); }