• 树状数组套线段树


    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
    ", get_rank(mn, mx, k));}
    		else if(opt == 2) {l = read(); r = read(); k = read(); get(l - 1, r); printf("%d
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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; }
    
  • 相关阅读:
    力扣第945题 使数组唯一的最小增量
    力扣第365题 水壶问题
    力扣面试题40 最小的k个数
    力扣第409题 最长回文串
    力扣第46题 全排列
    力扣第1160题 拼写单词
    力扣面试题01.06 字符串压缩
    力扣第695题 岛屿的最大面积
    树莓派 鼠标自动消失
    树莓派 VNC 远程桌面 同一个桌面
  • 原文地址:https://www.cnblogs.com/Sunny-r/p/15031791.html
Copyright © 2020-2023  润新知