1.P3380 【模板】二逼平衡树(树套树)
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 5e4 + 5;
const int mn = - 1e8 - 5;
const int mx = 1e8 + 5;
int n, m, a[N], cnt, rt[N], L, R, nl[N], nr[N];
struct node{int ls, rs, val;}tr[N * 200];
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
int lowbit(int x) {return x & (- x);}
void insert(int &k, int l, int r, int pos, int val)
{
if(!k) k = ++ cnt; tr[k].val += val;
if(l == r) return; int mid = (l + r) >> 1;
if(pos <= mid) insert(tr[k].ls, l, mid, pos, val);
else insert(tr[k].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
L = R = 0;
for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int get_rank(int l, int r, int k)
{
if(l == r) return 1; int mid = (l + r) >> 1, now = 0;
for(int i = 1; i <= L; i ++) now -= tr[tr[nl[i]].ls].val;
for(int i = 1; i <= R; i ++) now += tr[tr[nr[i]].ls].val;
if(k <= mid)
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
return get_rank(l, mid, k);
}
else
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
return now + get_rank(mid + 1, r, k);
}
}
int get_num(int l, int r, int k)
{
if(l == r) return l; int mid = (l + r) >> 1, now = 0;
for(int i = 1; i <= L; i ++) now -= tr[tr[nl[i]].ls].val;
for(int i = 1; i <= R; i ++) now += tr[tr[nr[i]].ls].val;
if(now >= k)
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
return get_num(l, mid, k);
}
else
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
return get_num(mid + 1, r, k - now);
}
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = read(); m = read();
for(int i = 1; i <= n; i ++)
{
a[i] = read();
for(int j = i; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[i], 1);
}
int opt, l, r, x, k, y;
while(m -- > 0)
{
opt = read();
if(opt == 1) {l = read(); r = read(); k = read(); get(l - 1, r); printf("%d\n", get_rank(mn, mx, k));}
else if(opt == 2) {l = read(); r = read(); k = read(); get(l - 1, r); printf("%d\n", get_num(mn, mx, k));}
else if(opt == 3)
{
x = read(); y = read();
for(int j = x; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[x], -1);
a[x] = y;
for(int j = x; j <= n; j += lowbit(j)) insert(rt[j], mn, mx, a[x], 1);
}
else if(opt == 4)
{
l = read(); r = read(); k = read();
get(l - 1, r); int em = get_rank(mn, mx, k); get(l - 1, r);
printf("%d\n", em == 1 ? -2147483647 : get_num(mn, mx, em - 1));
}
else if(opt == 5)
{
l = read(); r = read(); k = read();
get(l - 1, r); int em = get_rank(mn, mx, k + 1);
get(l - 1, r); int ans = get_num(mn, mx, em);
printf("%d\n", ans == mx ? 2147483647 : ans);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
2.P2617 Dynamic Rankings
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e5 + 5;
const int mx = 1e9 + 5;
int n, m, rt[N], a[N], cnt, nl[N], nr[N], L, R;
char s[5];
struct node{int ls, rs, siz;}tr[N * 300];
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
int lowbit(int x) {return x & (- x);}
void add(int &k, int l, int r, int pos, int val)
{
if(!k) k = ++ cnt;
tr[k].siz += val;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) add(tr[k].ls, l, mid, pos, val);
else add(tr[k].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
L = R = 0;
for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int get_num(int l, int r, int k)
{
if(l == r) return l;
int mid = (l + r) >> 1, sizls = 0;
for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].ls].siz;
for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].ls].siz;
if(sizls >= k)
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
return get_num(l, mid, k);
}
else
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
return get_num(mid + 1, r, k - sizls);
}
}
void work()
{
n = read(); m = read();
for(int i = 1; i <= n; i ++)
{
a[i] = read();
for(int j = i; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[i], 1);
}
for(int i = 1, x, y, k; i <= m; i ++)
{
scanf("%s", s); x = read(); y = read();
if(s[0] == 'Q')
{
k = read(); get(x - 1, y);
printf("%d\n", get_num(0, mx, k));
}
else
{
for(int j = x; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[x], -1);
a[x] = y;
for(int j = x; j <= n; j += lowbit(j)) add(rt[j], 0, mx, a[x], 1);
}
}
}
int main() {return work(), 0; }
3.P3157 [CQOI2011]动态逆序对
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int N = 100005;
int n, m, a[N], rt[N], cnt, L, R, nl[N], nr[N], po[N];
ll ans;
struct node{int ls, rs; int siz;}tr[N * 200];
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-')f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
return x * f;
}
int lowbit(int x) {return x & (- x);}
void add(int &x, int l, int r, int pos, int val)
{
if(!x) x = ++ cnt;
tr[x].siz += val;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) add(tr[x].ls, l, mid, pos, val);
else add(tr[x].rs, mid + 1, r, pos, val);
}
void get(int l, int r)
{
L = R = 0;
for(int i = l; i; i -= lowbit(i)) nl[++ L] = rt[i];
for(int i = r; i; i -= lowbit(i)) nr[++ R] = rt[i];
}
int query(int l, int r, int val)
{
int mid = (l + r) >> 1, sizls = 0;
if(l == r) return 0;
for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].ls].siz;
for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].ls].siz;
if(val <= mid)
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
return query(l, mid, val);
}
else
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
return sizls + query(mid + 1, r, val);
}
}
int ask(int l, int r, int val)
{
int mid = (l + r) >> 1, sizls = 0;
if(l == r) return 0;
for(int i = 1; i <= L; i ++) sizls -= tr[tr[nl[i]].rs].siz;
for(int i = 1; i <= R; i ++) sizls += tr[tr[nr[i]].rs].siz;
if(val <= mid)
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].ls;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].ls;
return sizls + ask(l, mid, val);
}
else
{
for(int i = 1; i <= L; i ++) nl[i] = tr[nl[i]].rs;
for(int i = 1; i <= R; i ++) nr[i] = tr[nr[i]].rs;
return ask(mid + 1, r, val);
}
}
void work()
{
n = read(); m = read();
for(int i = 1; i <= n; i ++)
{
a[i] = read(); po[a[i]] = i; get(0, i); ans += ask(1, n, a[i]);
for(int j = i; j <= n; j += lowbit(j)) add(rt[j], 1, n, a[i], 1);
//在插入之前直接统计就好 ,不用再循环一遍
}
for(int i = 1, x; i <= m; i ++)
{
x = read();
printf("%lld\n", ans);
get(po[x], n); ans -= query(1, n, x);
get(0, po[x] - 1); ans -= ask(1, n, x);
for(int j = po[x]; j <= n; j += lowbit(j)) add(rt[j], 1, n, x, -1);
}
}
int main() {return work(), 0; }