[置顶] 整体二分小结

时间:2022-07-17 15:03:40

整体二分小结

Ⅰ. 整体二分认知

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

  • 时间复杂度
    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 <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

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 <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

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 <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

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 <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

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;
}