zoukankan      html  css  js  c++  java
  • 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
    ", ans & 2147483647);
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    HZOJ 通讯
    HZOJ 礼物
    HZOI 可怜与超市
    高二小假期集训—D5
    [BZOJ3566][SHOI2014]概率充电器
    [***]HZOI20190714 T2熟练剖分
    20190714(又一次翻车……)
    HZOI20190714 T3建造游乐场
    模板—慢速乘
    模板—十进制快速幂
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9129627.html
Copyright © 2011-2022 走看看