Template - 「整体二分」
作者:互联网
写的简单。主要是留给自己做复习资料。
Dynamic Rankings.
给定一个含有 \(n\) 个数的序列 \(a_1,a_2 \dots a_n\),需要支持两种操作:
Q l r k
表示查询下标在区间 \([l,r]\) 中的第 \(k\) 小的数。C x y
表示将 \(a_x\) 改为 \(y\)。
引入整体二分。
其实就是我们对于二分到的一个值域 mid,去离线针对所有的询问进行 check。
具体是利用一些数据结构。
然后根据 check 和 mid 的大小将询问分为两拨,再分治下去解决问题。
参考于 OI-wiki 的板子很精简且思路便于理解。
#include <cstdio>
int Abs (int x) { return x < 0 ? -x : x; }
int Max (int x, int y) { return x > y ? x : y; }
int Min (int x, int y) { return x < y ? x : y; }
int Read () {
int x = 0, k = 1;
char s = getchar();
while (s < '0' || s > '9') {
if(s == '-')
k = -1;
s = getchar ();
}
while ('0' <= s && s <= '9')
x = (x << 3) + (x << 1) + (s ^ 48), s = getchar ();
return x * k;
}
void Write (int x) {
if(x < 0)
x = -x, putchar ('-');
if(x > 9)
Write (x / 10);
putchar (x % 10 + '0');
}
void Print (int x, char s) { Write (x), putchar (s); }
const int MAXN = 2e5 + 5;
char Opt[3];
int Ans[MAXN], BIT[MAXN], a[MAXN], n, m;
int Low_Bit (int x) {
return x & -x;
}
void Update (int k, int x) {
for (int i = k; i <= n; i += Low_Bit (i))
BIT[i] += x;
}
int Query (int k) {
int Res = 0;
for (int i = k; i >= 1; i -= Low_Bit (i))
Res += BIT[i];
return Res;
}
struct Node {
bool Type;
int Id, x, y, k;
Node () {}
Node (bool T, int I, int X, int Y, int K) {
Type = T, Id = I, x = X, y = Y, k = K;
}
} q[MAXN], Tmp[2][MAXN];
void Solve (int l, int r, int L, int R) {
if (l > r || L > R)
return ;
if (L == R) {
for (int i = l; i <= r; i++)
if (q[i].Type)
Ans[q[i].Id] = L;
return ;
}
// printf ("%d %d %d %d : //\n", l, r, L, R);
// for (int i = l; i <= r; i++)
// printf ("%d %d %d %d %d\n", q[i].Type, q[i].Id, q[i].x, q[i].y, q[i].k);
// printf ("//\n");
int Mid = (L + R) >> 1, Cnt0 = 0, Cnt1 = 0;
for (int i = l; i <= r; i++)
if (q[i].Type) {
int Check = Query (q[i].y) - Query (q[i].x - 1);
if (q[i].k <= Check)
Tmp[0][++Cnt0] = q[i];
else
q[i].k -= Check, Tmp[1][++Cnt1] = q[i];
}
else {
if (q[i].y <= Mid)
Update (q[i].x, q[i].k), Tmp[0][++Cnt0] = q[i];
else
Tmp[1][++Cnt1] = q[i];
}
for (int i = 1; i <= Cnt0; i++)
if (!Tmp[0][i].Type)
Update (Tmp[0][i].x, -Tmp[0][i].k);
for (int i = 1; i <= Cnt0; i++)
q[l + i - 1] = Tmp[0][i];
for (int i = 1; i <= Cnt1; i++)
q[l + Cnt0 + i - 1] = Tmp[1][i];
Solve (l, l + Cnt0 - 1, L, Mid), Solve (l + Cnt0, r, Mid + 1, R);
}
int main () {
n = Read (), m = Read ();
int p = 0, Tot = 0;
for (int i = 1, x; i <= n; i++)
x = Read (), q[++p] = Node (0, 0, i, x, 1), a[i] = x;
for (int i = 1, x, y; i <= m; i++) {
scanf ("%s", Opt + 1), x = Read (), y = Read ();
if (Opt[1] == 'Q') {
int k = Read ();
q[++p] = Node (1, ++Tot, x, y, k);
}
else
q[++p] = Node (0, 0, x, a[x], -1), q[++p] = Node (0, 0, x, y, 1), a[x] = y;
}
Solve (1, p, 0, 1e9);
for (int i = 1; i <= Tot; i++)
Print (Ans[i], '\n');
return 0;
}
标签:二分,Node,return,int,void,整体,char,MAXN,Template 来源: https://www.cnblogs.com/LoveMiffyForever/p/15902483.html