整体二分小结

整体二分小结

Ⅰ. 整体二分认知

  • 摘抄部分 2013 许昊然论文-《浅谈数据结构题的几个非经典解法》
    特么的论文用了啥 j8 加密编码, 还不能复制。。又不是不标出处。
    整体二分小结_第1张图片

  • 时间复杂度
    T(LQ,Lans):=LQ,Lans
    O(f(n)),
    T(LQ,Lans)=T(S0,Lans2)+T(LQS0,Lans2)+O(f(LQ))
    T(|Q|,|C|)O(f(Q))logC,|Q|,|C|
    PS:O(f(n))O(n),n,O(n),

  • 时间复杂度分析举例
    ksmallest numberO(LQlogN)
    O((N+Q)logNlogC)

Ⅱ. 题目讲解

POJ 2104 K-th Number

题意:

N105,|Ai|109,Q5×103
l,r,k:[l,r]ksmallest

代码:

//
//  Created by TaoSama on 2016-02-14
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int Q = 1e4 + 10;

struct Query {
    int x, y, k;
    int id, type;
    void print() {
        printf("%d %d %d %d %d\n", x, y, k, id, type);
    }
} q[N + Q], q1[N + Q], q2[N + Q];

struct BIT {
    int n, b[N];
    void init(int _n) {n = _n; memset(b, 0, sizeof b);}
    void add(int i, int x) {
        for(; i <= n; i += i & -i) b[i] += x;
    }
    int sum(int i) {
        int ret = 0;
        for(; i; i -= i & -i) ret += b[i];
        return ret;
    }
} bit;

int n, m, a[N];
int ans[Q];

void solve(int qL, int qR, int l, int r) {
    if(qL > qR) return;
    if(l == r) {
        for(int i = qL; i <= qR; ++i)
            if(q[i].type == 2) ans[q[i].id] = l;
        return;
    }
    int m = l + r >> 1;

    //check m
    int f = 0, g = 0;
    for(int i = qL; i <= qR; ++i) {
        if(q[i].type == 1) {
            if(q[i].x <= m) {
                bit.add(q[i].id, q[i].y);
                q1[f++] = q[i];
            } else q2[g++] = q[i];
        } else {
            int small = bit.sum(q[i].y) - bit.sum(q[i].x - 1);
            if(small >= q[i].k) q1[f++] = q[i];
            else {
                q[i].k -= small;
                q2[g++] = q[i];
            }
        }
    }
    //clear
    for(int i = 0; i < f; ++i)
        if(q1[i].type == 1) bit.add(q1[i].id, -q1[i].y);

    //copy back
    memcpy(q + qL, q1, f * sizeof(Query));
    memcpy(q + qL + f, q2, g * sizeof(Query));

    solve(qL, qL + f - 1, l, m);
    solve(qL + f, qR, m + 1, r);
}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d", &n, &m) == 2) {
        bit.init(n);
        int idx = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", a + i);
            q[++idx] = (Query) {a[i], 1, INF, i, 1};
        }
        for(int i = 1; i <= m; ++i) {
            int x, y, k; scanf("%d%d%d", &x, &y, &k);
            q[++idx] = (Query) {x, y, k, i, 2};
        }

        solve(1, idx, -INF, INF);
        for(int i = 1; i <= m; ++i)
            printf("%d\n", ans[i]);
    }
    return 0;
}

ZOJ 2112 Dynamic Rankings

题意:

N5×104,0<Ai109,Q5×104
Q l r k:[l,r]ksmallest
C i x:Aix

分析:

,

代码:

//
//  Created by TaoSama on 2016-02-14
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int Q = 2e4 + 10;

struct Query {
    int x, y, k;
    int id, type;
    void print() {
        printf("%d %d %d %d %d\n", x, y, k, id, type);
    }
} q[N + Q], q1[N + Q], q2[N + Q];

struct BIT {
    int n, b[N];
    void init(int _n) {n = _n; memset(b, 0, sizeof b);}
    void add(int i, int x) {
        for(; i <= n; i += i & -i) b[i] += x;
    }
    int sum(int i) {
        int ret = 0;
        for(; i; i -= i & -i) ret += b[i];
        return ret;
    }
} bit;

int n, m, a[N];
int ans[Q];

void solve(int qL, int qR, int l, int r) {
    if(qL > qR) return;
    if(l == r) {
        for(int i = qL; i <= qR; ++i)
            if(q[i].type == 2) ans[q[i].id] = l;
        return;
    }
    int m = l + r >> 1;

    //check m
    int f = 0, g = 0;
    for(int i = qL; i <= qR; ++i) {
        if(q[i].type == 1) {
            if(q[i].x <= m) {
                bit.add(q[i].id, q[i].y);
                q1[f++] = q[i];
            } else q2[g++] = q[i];
        } else {
            int small = bit.sum(q[i].y) - bit.sum(q[i].x - 1);
            if(small >= q[i].k) q1[f++] = q[i];
            else {
                q[i].k -= small;
                q2[g++] = q[i];
            }
        }
    }
    //clear
    for(int i = 0; i < f; ++i)
        if(q1[i].type == 1) bit.add(q1[i].id, -q1[i].y);

    //copy back
    memcpy(q + qL, q1, f * sizeof(Query));
    memcpy(q + qL + f, q2, g * sizeof(Query));

    solve(qL, qL + f - 1, l, m);
    solve(qL + f, qR, m + 1, r);
}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    int t; scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        bit.init(n);
        int idx = 0, cnt = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", a + i);
            q[++idx] = (Query) {a[i], 1, INF, i, 1};
        }
        for(int i = 1; i <= m; ++i) {
            char op[2]; int x, y, k;
            scanf("%s%d%d", op, &x, &y);
            if(*op == 'Q') {
                scanf("%d", &k);
                q[++idx] = (Query) {x, y, k, ++cnt, 2};
            } else {
                q[++idx] = (Query) {a[x], -1, INF, x, 1};
                a[x] = y;
                q[++idx] = (Query) {a[x], 1, INF, x, 1};
            }
        }

//      for(int i = 1; i <= idx; ++i) q[i].print();

        solve(1, idx, 0, INF);
        for(int i = 1; i <= cnt; ++i)
            printf("%d\n", ans[i]);
    }
    return 0;
}

BZOJ 3110 K大数查询

题意:

N5×104,,Q5×104
1 a b c:[l,r]c,|c|N
2 a b c:[l,r]clargest,cLL_MAX

分析:

cnc+1,clargestcsmallest
,线
,ans=nans+1

代码:

//
//  Created by TaoSama on 2016-02-15
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int Q = 5e4 + 10;

typedef long long LL;

struct Query {
    int a, b; LL c;
    int id;
} q[Q], q1[Q], q2[Q];

struct SegTree {
    LL sum[N << 2], add[N << 2];
    void pushUp(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    void pushDown(int rt, int m) {
        if(add[rt]) {
            sum[rt << 1] += (m - m / 2) * add[rt];
            sum[rt << 1 | 1] += (m / 2) * add[rt];
            add[rt << 1] += add[rt];
            add[rt << 1 | 1] += add[rt];
            add[rt] = 0;
        }
    }
    void update(int L, int R, int v, int l, int r, int rt) {
        if(L <= l && r <= R) {
            sum[rt] += v * (r - l + 1);
            add[rt] += v;
            return;
        }
        pushDown(rt, r - l + 1);
        int m = l + r >> 1;
        if(L <= m) update(L, R, v, l, m, rt << 1);
        if(R > m) update(L, R, v, m + 1, r, rt << 1 | 1);
        pushUp(rt);
    }
    LL query(int L, int R, int l, int r, int rt) {
        if(L <= l && r <= R) return sum[rt];
        pushDown(rt, r - l + 1);
        int m = l + r >> 1;
        LL ret = 0;
        if(L <= m) ret += query(L, R, l, m, rt << 1);
        if(R > m) ret += query(L, R, m + 1, r, rt << 1 | 1);
        return ret;
    }
} T;

int n, m;
int ans[Q];

void solve(int L, int R, int l, int r) {
    if(L > R) return;
    if(l == r) {
        for(int i = L; i <= R; ++i)
            if(q[i].id > 0) ans[q[i].id] = l;
        return;
    }
    int m = l + r >> 1;
    int f = 0, g = 0;
    for(int i = L; i <= R; ++i) {
        if(q[i].id < 0) {
            if(q[i].c <= m) {
                T.update(q[i].a, q[i].b, 1, 1, n, 1);
//              printf("add %d: %d %d %lld %d\n", i, q[i].a, q[i].b, q[i].c, m);
                q1[f++] = q[i];
            } else q2[g++] = q[i];
        } else {
            LL small = T.query(q[i].a, q[i].b, 1, n, 1);
//          printf("query %d: %d %d %lld small=%lld\n", i,
//                  q[i].a, q[i].b, q[i].c, small);
            if(small >= q[i].c) q1[f++] = q[i];
            else {
                q[i].c -= small;
                q2[g++] = q[i];
            }
        }
    }
    for(int i = 0; i < f; ++i)
        if(q1[i].id < 0) T.update(q1[i].a, q1[i].b, -1, 1, n, 1);

    memcpy(q + L, q1, f * sizeof(Query));
    memcpy(q + L + f, q2, g * sizeof(Query));

    solve(L, L + f - 1, l, m);
    solve(L + f, R, m + 1, r);
}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d", &n, &m) == 2) {
        memset(&T, 0, sizeof T);
        int cnt = 0;
        for(int i = 1; i <= m; ++i) {
            int op, a, b; LL c; scanf("%d%d%d%lld", &op, &a, &b, &c);
            if(op == 1) c = n - c + 1;  //change number so as to be k-th
            q[i] = (Query) {a, b, c, op == 1 ? -1 : ++cnt};
        }
        solve(1, m, 1, 2 * n + 1);
        for(int i = 1; i <= cnt; ++i)
            printf("%d\n", n - ans[i] + 1); //change back
    }
    return 0;
}

Tsinsen A1333 矩阵乘法

题意:

NN,N500,Q6×104
x1,y1,x2,y2,k:(x1,y1),(x2,y2)ksmallest

分析:

xhr,BIT

代码:

//
//  Created by TaoSama on 2016-02-15
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e2 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int Q = 6e4 + 10;

struct Query {
    int x1, y1, x2, y2, k;
    int id;
} q[N * N + Q], q1[N * N + Q], q2[N * N + Q];

struct BIT {
    int n, b[N][N];
    void init(int _n) {n = _n; memset(b, 0, sizeof b);}
    void add(int x, int y, int v) {
        for(int i = x; i <= n; i += i & -i)
            for(int j = y; j <= n; j += j & -j)
                b[i][j] += v;
    }
    int sum(int x, int y) {
        int ret = 0;
        for(int i = x; i; i -= i & -i)
            for(int j = y; j; j -= j & -j)
                ret += b[i][j];
        return ret;
    }
    int sum(int x1, int y1, int x2, int y2) {
        return sum(x2, y2) - sum(x1 - 1, y2) - sum(x2, y1 - 1)
               + sum(x1 - 1, y1 - 1);
    }
} bit;

int n, m, ans[Q];

void solve(int L, int R, int l, int r) {
    if(L > R) return;
    if(l == r) {
        for(int i = L; i <= R; ++i)
            if(q[i].id) ans[q[i].id] = l;
        return;
    }
    int m = l + r >> 1;
    int f = 0, g = 0;
    for(int i = L; i <= R; ++i) {
        if(!q[i].id) {
            if(q[i].k <= m) {
                bit.add(q[i].x1, q[i].y1, 1);
                q1[f++] = q[i];
            } else q2[g++] = q[i];
        } else {
            int small = bit.sum(q[i].x1, q[i].y1, q[i].x2, q[i].y2);
            if(small >= q[i].k) q1[f++] = q[i];
            else {
                q[i].k -= small;
                q2[g++] = q[i];
            }
        }
    }
    for(int i = 0; i < f; ++i)
        if(!q1[i].id) bit.add(q1[i].x1, q1[i].y1, -1);

    memcpy(q + L, q1, f * sizeof(Query));
    memcpy(q + L + f, q2, g * sizeof(Query));

    solve(L, L + f - 1, l, m);
    solve(L + f, R, m + 1, r);
}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d", &n, &m) == 2) {
        bit.init(n);
        int idx = 0;
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                int x; scanf("%d", &x);
                q[++idx] = (Query) {i, j, 0, 0, x, 0};
            }
        }
        for(int i = 1; i <= m; ++i) {
            int x1, y1, x2, y2, k;
            scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &k);
            q[++idx] = (Query) {x1, y1, x2, y2, k, i};
        }
        solve(1, idx, 1, INF);
        for(int i = 1; i <= m; ++i)
            printf("%d\n", ans[i]);
    }
    return 0;
}

你可能感兴趣的:(整体二分小结)