首页 > 代码库 > BIT

BIT

POJ 2481

给出n个区间,第i个用\((x_i,y_i)\)表示,定义包含:i包含j等价于\(x_i\leq x_j\land y_j\leq y_i \land\lnot(x_i=x_j\land y_i=y_j)\),问对于每个区间,有多少个区间包含它。

BIT 做法:将区间排序,对所有i包含j使得i排在j前面,然后从前往后用BIT统计出所求。

需要注意的地方是两个区间相等的情况的处理,这时可以对原始区间离散化(相同的保存一份,并且统计出个数),在更新时一次更新所有;或者不离散化,每次统计第i个区间时,如果前一个区间和它相同,直接ans[i] = ans[i-1]。

离散化的代码:

# include <cstdio># include <cstring># include <algorithm>const int maxn = 100005;int n;int a[maxn], b[maxn], r[maxn], id[maxn];int f[maxn], fc[maxn];int c[maxn];int ans[maxn];int lb(int x) {    return x & -x;}bool cmp(const int x, const int y) {    if (a[x] == a[y]) return b[x] > b[y];    return a[x] < a[y];}void inc(int x, int cc) {    for (; x < maxn; x += lb(x)) c[x] += cc;}int GetSum(int x) {    int r; for (r = 0; x > 0; x-=lb(x)) r += c[x];    return r;}int main(){    while (scanf("%d", &n), n) {        for (int i = 0; i < n; ++i) {            scanf("%d%d", &a[i], &b[i]);            ++a[i], ++b[i];        }        for (int i = 0; i < n; ++i) r[i] = i;        std::sort(r, r+n, cmp);        int m = 0;        id[r[0]] = 0;        f[0] = r[0];        memset(fc, 0, sizeof(fc));        ++fc[0];        for (int i = 1; i < n; ++i) {            int idx = r[i], pidx = r[i-1];            if (a[idx]!=a[pidx] || b[idx]!=b[pidx]) ++m, f[m] = idx;            ++fc[m];            id[idx] = m;        }        ++m;        memset(c, 0, sizeof(c));        for (int i = 0; i < m; ++i) {            ans[i] = GetSum(maxn-1) - GetSum( b[ f[i] ] - 1 );            inc( b[ f[i] ], fc[i] );        }        for (int i = 0; i < n; ++i) {            if (i) printf(" ");            printf("%d", ans[ id[i] ]);        }        printf("\n");    }    return 0;}

没有离散化的代码:

# include <cstring># include <cstdio># include <algorithm>int n;const int maxn = 100005;int mx;int x[maxn], y[maxn], r[maxn];int c[maxn];int ans[maxn];bool cmp(const int i, const int j) {    if (x[i] == x[j]) return y[j] < y[i];    return x[i] < x[j];}bool judge(int i){    if (i) {        int u = r[i], v = r[i-1];        if (x[u]==x[v] && y[u]==y[v]) return true;    }    return false;}int lb(int x) {return x&-x;}int GetSum(int x) {    int r; for (r = 0; x>0; x-=lb(x)) r+=c[x]; return r;}void inc(int x) { for (;x<=mx;x+=lb(x)) ++c[x];}int main(){    while (scanf("%d", &n), n) {        mx = 1;        for (int i = 0; i < n; ++i) scanf("%d%d", &x[i], &y[i]), mx = std::max(mx, ++y[i]);        for (int i = 0; i < n; ++i) r[i] = i;        std::sort(r, r+n, cmp);        memset(c, 0, sizeof(c[0])*(mx+1));        memset(ans, 0, sizeof(ans[0])*n);        for (int i = 0; i < n; ++i) {            int u = r[i];            if (judge(i)) ans[u] = ans[ r[i-1] ];            else ans[u] = GetSum(mx) - GetSum(y[u]-1);            inc(y[u]);        }        for (int i = 0; i < n; ++i) {            printf(i ? " %d":"%d", ans[i]);        }        printf("\n");    }    return 0;}

 

POJ 3321

先处理出dfs序列,然后对每颗子树的根直接用BIT统计即可。

vector 超时了,使用邻接表的代码:

# include <cstdio># include <cstring>const int maxn = 100005;int n,m;int c[maxn];bool a[maxn];int id[maxn];int right[maxn];int cntId;int cntEdge;int first[maxn], next[maxn*2], wor[maxn*2];void Add(int u, int v){    int head = first[u];    first[u] = ++cntEdge;    next[cntEdge] = head;    wor[cntEdge] = u ^ v;}void dfs(int u, int fa) {    id[u] = ++cntId;    for (int e = first[u]; e != -1; e = next[e]) {        if (wor[e]!=(u^fa)) dfs(wor[e]^u, u);    }    right[ id[u] ] = cntId;}int lb(int x) {return x&-x;}void Update(int x, int cc) {for(;x<=n;x+=lb(x)) c[x]+=cc;}int GetSum(int x) { int r; for (r=0;x>0;x-=lb(x)) r+=c[x]; return r;}int main(){    while (scanf("%d", &n) != EOF) {        cntEdge = 0;        memset(first, -1, sizeof(first));        for (int i = 1; i < n; ++i) {            int u, v; scanf("%d%d", &u, &v);            Add(u, v); Add(v, u);        }        cntId = 0;        dfs(1, -1);        for (int i = 1; i <= n; ++i) c[i] = lb(i), a[i] = true;        scanf("%d", &m);        for (int i = 0; i < m; ++i) {            char od[5]; int x;            scanf("%s%d", od, &x);            if (od[0] == C) {                a[x] = !a[x];                Update(id[x], a[x]?1:-1);            } else {                printf("%d\n", GetSum(right[ id[x] ]) - GetSum(id[x]-1));            }        }    }    return 0;}

BIT