bzoj 1227 [SDOI2009]虔诚的墓主人

疯狂re 换了一种写法才过。。。

 

思路:将x轴离散化,处理出来每个点上下左右一个有多少个点, 对于同一行的两个点来说,他们之间的

这些空的点都是可以一起算的,我们用树状数组按y轴从小到大维护 每一列的贡献和。。 

 

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 1e5 + 10;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;

int x[N], y[N], tot1, tot2, n, m, w, k,f[N][11], sum[N];

struct Bit {
    int a[N];
    void modify(int x, int v) {
        for(int i = x; i <= tot1; i += i & -i) {
            a[i] += v;
        }
    }

    int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }

    int query(int l, int r) {
        r = min(tot1, r);
        if(l > r) return 0;
        return sum(r) - sum(l - 1);
    }

}bit;

struct Point {
    Point(int x = 0, int y = 0) {
        this -> x = x;
        this -> y = y;
    }
    int x, y, l, r, u, d;

    bool operator < (const Point &rhs) const {
        if(y == rhs.y) return x < rhs.x;
        return y < rhs.y;
    }
}p[N];

vector<Point> v[N];

int C(int a, int b) {
    return f[a][b];
}

void init() {
    p[0].y = -1; p[w + 1].y = -1;
    for(int i = 0; i < N; i++) {
        for(int j = 0; j <= 10 && j <= i; j++) {
            if(!j || j == i) f[i][j] = 1;
            else f[i][j] = f[i - 1][j] + f[i - 1][j - 1];
        }
    }
}

int main() {

    scanf("%d%d%d", &n, &m, &w);
    init();

    for(int i = 1; i <= w; i++) {
        scanf("%d%d", &p[i].x, &p[i].y);
        x[++tot1] = p[i].x;
        y[++tot2] = p[i].y;
    }

    scanf("%d", &k);
    sort(x + 1, x + tot1 + 1); tot1 = unique(x + 1, x + tot1 + 1) - x - 1;
    sort(y + 1, y + tot2 + 1); tot2 = unique(y + 1, y + tot2 + 1) - y - 1;

    sort(p + 1, p + w + 1);
    for(int i = 1; i <= w; i++) p[i].x = lower_bound(x + 1, x + tot1 + 1, p[i].x) - x;

    int ans = 0, tmp = 0;
    for(int i = 1; i <= w; i++) {
        if(p[i].y == p[i -1].y) tmp++;
        else tmp = 1;
        p[i].l = tmp;
        sum[p[i].x]++;
        p[i].u = sum[p[i].x];
    }

    tmp = 0;

    for(int i = w; i >= 1; i--) {
        if(p[i].y == p[i + 1].y) tmp++;
        else tmp = 1;
        p[i].r = tmp; p[i].d = sum[p[i].x] - p[i].u;
    }


    for(int i = 1; i <= w; i++) {
        bit.modify(p[i].x, C(p[i].u, k) * C(p[i].d, k) - bit.query(p[i].x, p[i].x));
        if(i > 1 && p[i].y == p[i - 1].y)
            ans += C(p[i - 1].l, k) * C(p[i].r, k) * bit.query(p[i - 1].x + 1, p[i].x - 1);
    }

    printf("%d\n", ans & 2147483647);
    return 0;
}

/*
*/

 

posted @ 2018-06-03 16:45  NotNight  阅读(105)  评论(0编辑  收藏  举报