「SDOI2009」墓の敬虔な所有者

ポータル
Luogu

問題解決のためのアイデア

言うこと離散何もありません
暴力的なアイデアは、常緑樹の数ダウン、アップ、右、左に店に維持いくつかのデータ構造で、すべての墓を列挙して、いくつかの統計的なプログラムの組み合わせを使用することであります。
しかし、側トレリスある\(1E9 \)レベル、このアプローチ萎凋は
常緑樹から始める考えてみましょう。
我々は、長手方向に同じ垂直隣接常緑樹における両者の墓の寄与が同じで見つけることができます。
したがって、我々は、各セグメントツリーメンテナンスの各垂直、水平寄与の常緑樹を使用することができる保ちます。

詳細注意事項

  • GUGU区

参照コード

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#include <vector>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= (c == '-'), c = getchar();
    while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    s = f ? -s : s;
}

typedef long long LL;
const LL p = 2147483648;
const int _ = 100010;

int n, k, c[12][_];
int xx, yy, X[_], Y[_];
vector < int > vec[_];
struct node{ int x, y; }t[_];
int sum[_ << 2], R[_ << 2], L[_ << 2], val[_];

inline int lc(int rt) { return rt << 1; }

inline int rc(int rt) { return rt << 1 | 1; }

inline void pushup(int rt) { sum[rt] = (sum[lc(rt)] + sum[rc(rt)]) % p; }

inline void build(int rt = 1, int l = 1, int r = yy) {
    if (l == r) { R[rt] = val[l]; return ; }
    int mid = (l + r) >> 1;
    build(lc(rt), l, mid), build(rc(rt), mid + 1, r);
}

inline void update(int id, int rt = 1, int l = 1, int r = yy) {
    if (l == r) {
        --R[rt], ++L[rt], sum[rt] = 1ll * c[k][L[rt]] * c[k][R[rt]] % p;
        return ;
    }
    int mid = (l + r) >> 1;
    if (id <= mid) update(id, lc(rt), l, mid);
    else update(id, rc(rt), mid + 1, r);
    pushup(rt);
}

inline LL query(int ql, int qr, int rt = 1, int l = 1, int r = yy) {
    if (ql <= l && r <= qr) return sum[rt];
    int mid = (l + r) >> 1; LL res = 0;
    if (ql <= mid) res = (res + query(ql, qr, lc(rt), l, mid)) % p;
    if (qr > mid) res = (res + query(ql, qr, rc(rt), mid + 1, r)) % p;
    return res;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.in", "r", stdin);
#endif
    read(n), read(n), read(n);
    for (rg int i = 1; i <= n; ++i) {
        read(t[i].x), X[i] = t[i].x;
        read(t[i].y), Y[i] = t[i].y;
    }
    sort(X + 1, X + n + 1), xx = unique(X + 1, X + n + 1) - X - 1;
    for (rg int i = 1; i <= n; ++i) t[i].x = lower_bound(X + 1, X + xx + 1, t[i].x) - X;
    sort(Y + 1, Y + n + 1), yy = unique(Y + 1, Y + n + 1) - Y - 1;
    for (rg int i = 1; i <= n; ++i) t[i].y = lower_bound(Y + 1, Y + yy + 1, t[i].y) - Y;
    read(k), c[0][0] = 1;
    for (rg int i = 1; i <= n; ++i) {
        ++val[t[i].y], vec[t[i].x].push_back(t[i].y);
        c[0][i] = 1;
        for (rg int j = 1; j <= k; ++j)
            c[j][i] = (c[j][i - 1] + c[j - 1][i - 1]) % p;
    }
    build();
    LL res = 0;
    for (rg int i = 1; i <= xx; ++i) {
        sort(vec[i].begin(), vec[i].end());
        if (!vec[i].empty()) update(vec[i][0]);
        int siz = vec[i].size();
        for (rg int j = 1; j < siz; ++j) {
            if (vec[i][j - 1] + 1 <= vec[i][j] - 1 && j >= k && siz - j >= k)
                res = (res + 1ll * query(vec[i][j - 1] + 1, vec[i][j] - 1) * c[k][j] % p * c[k][siz - j] % p) % p;
            update(vec[i][j]);
        }
    }
    printf("%lld\n", res);
    return 0;
}

エンドSahua \(qwq \)

おすすめ

転載: www.cnblogs.com/zsbzsb/p/11746086.html