板子题不多说了。
如果感觉看了半天网上题解看不懂的话,我建议:罚你重抄树状数组
联动:<Click Here> 带插入区间 kth
树状数组套线段树
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cstring>
#include<cctype>
using namespace std;
#define lowbit(x) (x&-x)
const int MAXN = 200005;
const int MAXS = 300 * MAXN;
int n, m, tot = 0, a[MAXN], t[MAXN], RtOri[MAXN], RtMod[MAXN], LC[MAXS], RC[MAXS], Seg[MAXS];
int ListBas[MAXN], ListSub[MAXN];
struct SM
{
bool t;
int a, b, c;
SM(bool aa=0, int bb=0, int cc=0, int dd=0)
{
t = aa;
a = bb;
b = cc;
c = dd;
}
}o[MAXN];
void Init()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
a[0] = n;
char typ;
for (int ori, tar, kth, i = 1; i <= m; ++i)
{
scanf(" %c %d%d", &typ, &ori, &tar);
if (typ == 'Q')
{
scanf("%d", &kth);
o[i] = SM(0, ori, tar, kth);
}
else
{
o[i] = SM(1, ori, tar, 0);
a[++n] = tar;
}
}
memcpy(t, a, sizeof(a));
sort(t + 1, t + 1 + n);
t[0] = unique(t + 1, t + 1 + n) - t - 1;
n = a[0];
for (int i = 1; i <= n; ++i) a[i] = lower_bound(t + 1, t + 1 + t[0], a[i]) - t;
for (int i = 1; i <= m; ++i) if (o[i].t) o[i].b = lower_bound(t + 1, t + 1 + t[0], o[i].b) - t;
}
void SegIns_Ini(int &Pos, int Pre, int L, int R, int Tar)
{
LC[Pos = ++tot] = LC[Pre], RC[Pos] = RC[Pre], Seg[Pos] = Seg[Pre] + 1;
if (L == R) return;
int Mid = L + R >> 1;
if (Tar <= Mid)
{
SegIns_Ini(LC[Pos], LC[Pre], L, Mid, Tar);
return;
}
SegIns_Ini(RC[Pos], RC[Pre], Mid + 1, R, Tar);
}
void SegIns_Mod(int &Pos, int L, int R, int Tar, int Val)
{
Seg[Pos ? Pos : (Pos = ++tot)] += Val;
if (L == R) return;
int Mid = L + R >> 1;
if (Tar <= Mid)
{
SegIns_Mod(LC[Pos], L, Mid, Tar, Val);
return;
}
SegIns_Mod(RC[Pos], Mid + 1, R, Tar, Val);
}
int GetSize()
{
int SumBas = 0, SumSub = 0;
for (int i = 1; i <= ListBas[0]; ++i) SumBas += Seg[LC[ListBas[i]]];
for (int i = 1; i <= ListSub[0]; ++i) SumSub += Seg[LC[ListSub[i]]];
return SumBas - SumSub;
}
int SegQuery(int L, int R, int qL, int qR, int Kth)
{
if (L == R) return L;
int LeftSize = GetSize() + Seg[LC[qR]] - Seg[LC[qL]];
int Mid = L + R >> 1;
if (Kth <= LeftSize)
{
for (int i = 1; i <= ListBas[0]; ++i) ListBas[i] = LC[ListBas[i]];
for (int i = 1; i <= ListSub[0]; ++i) ListSub[i] = LC[ListSub[i]];
return SegQuery(L, Mid, LC[qL], LC[qR], Kth);
}
for (int i = 1; i <= ListBas[0]; ++i) ListBas[i] = RC[ListBas[i]];
for (int i = 1; i <= ListSub[0]; ++i) ListSub[i] = RC[ListSub[i]];
return SegQuery(Mid + 1, R, RC[qL], RC[qR], Kth - LeftSize);
}
int Query(int L, int R, int Kth)
{
ListBas[0] = ListSub[0] = 0;
for (int i = R; i; i -= lowbit(i)) ListBas[++ListBas[0]] = RtMod[i];
for (int i = L - 1; i; i -= lowbit(i)) ListSub[++ListSub[0]] = RtMod[i];
return SegQuery(1, t[0], RtOri[L-1], RtOri[R], Kth);
}
void Mod(int Pos, int Val)
{
for (int i = Pos; i <= n; i += lowbit(i)) SegIns_Mod(RtMod[i], 1, t[0], a[Pos], Val);
}
void SegIniZero(int &Pos, int L, int R)
{
Pos = ++tot;
if (L == R) return;
int Mid = L + R >> 1;
SegIniZero(LC[Pos], L, Mid);
SegIniZero(RC[Pos], Mid + 1, R);
}
void SegInit()
{
SegIniZero(RtOri[0], 1, t[0]);
for (int i = 1; i <= n; ++i) SegIns_Ini(RtOri[i], RtOri[i-1], 1, t[0], a[i]);
}
void SegWork()
{
for (int i = 1; i <= m; ++i)
{
if (!o[i].t)
{
printf("%d\n", t[Query(o[i].a, o[i].b, o[i].c)]);
continue;
}
Mod(o[i].a, -1);
a[o[i].a] = o[i].b;
Mod(o[i].a, +1);
}
}
void Main()
{
SegInit();
SegWork();
}
int main()
{
Init();
Main();
return 0;
}
整体二分 / 树状数组套平衡树
什么?
我先鸽为敬.jpg