• 【BZOJ1901】Dynamic Rankings


    Link: https://www.luogu.com.cn/problem/P2617


    树状数组套可持久化线段树


    Solution

    我们现在先只使用主席树。
    那么每次修改都要把版本 (x) 的树枝挪一挪。 (O(log n)) 可以解决挪动。
    但是会影响到之后版本的树的 Size ,如果全部改掉最多需要 (O(nlog^2 n))
    这是万万不行的。

    为什么会影响到之后版本树的 Size ?

    先来看一个问题。主席树的每个版本只有 (log n) 个结点吗?
    不是吧。那是什么呢?是之前所有版本的前缀和。
    Size 同样,也是前缀和。

    前缀和可以用树状数组维护、
    那么,只需要把 主席树的版本 当成 树状数组的一个数 就可以了
    树状数组维护的 (2^i) 长度区间的和,在树套树意义下就是 (2^i) 个版本的,主席树的和
    当然,因为“加一个版本主席树”的操作等同于“加一条链”,所以其实等同于插入一个数。

    然后你会发现所谓的主席树就是一个谎言,我们套的其实是好多捆线段树的链
    但是,虽然没有往前面的版本连线,
    这个东西的基本思想仍然有可持久化线段树的部分,不过用了另一种方式维护多个版本的总和。
    ……但是省空间的部分就完全不一样了。
    标签打多了,有时候把某个算法改动一下,总会有套不上的时候嘛。

    时空复杂度 (O(nlog^2 n))

    查询的场合,在两个版本上同时跑。
    因为要统计前缀和,所以要带上减去不同次 lowbit 的那一串不同版本的主席树。

    把询问的下标当作查询的位置居然过了样例..



    Code

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int MAXN = 1e5 + 10;
    #define lowbit(i) ((i)&-(i))
    int n, m;
    int a[MAXN];
    int EL[MAXN<<1]={};
    struct Operat
    {
    	bool t;
    	int l, r, x;
    	Operat(bool tt=0, int ll=0, int rr=0, int xx=0)
    	{
    		t = tt;
    		l = ll;
    		r = rr;
    		x = xx;
    	}
    }Op[MAXN];
    int SegTot = 0;
    int Rt[MAXN<<8];
    int Lc[MAXN<<8], Rc[MAXN<<8];
    int Size[MAXN<<8];
    //Mei You Int Size MAXN
    void PersisTree_Add(int &Pos, int L, int R, int Val, int Add) //NO PREPOS
    {
    	if (!Pos) Pos = ++SegTot;
    	Size[Pos] += Add;
    	if (L == R) return;
    	int Mid = L + R >> 1;
    	if (Val <= Mid)
    	{
    		PersisTree_Add(Lc[Pos], L, Mid, Val, Add);
    	}
    	else
    	{
    		PersisTree_Add(Rc[Pos], Mid + 1, R, Val, Add);
    	}
    }
    void BIT_Add(int Pos, int Val, int Opt)
    {
    	while (Pos <= n)
    	{
    		PersisTree_Add(Rt[Pos], 1, EL[0], Val, Opt); 
    		Pos += lowbit(Pos);
    	}
    }
    int ListL[500], ListR[500];
    #define LUP for (int i = 1; i <= ListL[0]; ++i)
    #define RUP for (int i = 1; i <= ListR[0]; ++i)
    int Qkth(int l, int r, int k)
    {
    	if (l == r) return l;
    	int Mid = l + r >> 1;
    	int LeftSiz = 0;
    	RUP {
    		LeftSiz += Size[Lc[ListR[i]]];
    	}
    	LUP {
    		LeftSiz -= Size[Lc[ListL[i]]];
    	}
    	if (k <= LeftSiz)
    	{
    		LUP ListL[i] = Lc[ListL[i]];
    		RUP ListR[i] = Lc[ListR[i]];
    		return Qkth(l, Mid, k);
    	}
    	// else
    	LUP ListL[i] = Rc[ListL[i]];
    	RUP ListR[i] = Rc[ListR[i]];
    	return Qkth(Mid + 1, r, k - LeftSiz);
    }
    int BIT_SumAndKth(int l, int r, int k)
    {
    	--l;
    	ListL[0] = ListR[0] = 0;
    	while(l)
    	{
    		ListL[++ListL[0]] = Rt[l];
    		l -= lowbit(l);
    	}
    	while(r)
    	{
    		ListR[++ListR[0]] = Rt[r];
    		r -= lowbit(r);
    	}
    	return Qkth(1, EL[0], k);
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0); cout.tie(0);
    	cin >> n >> m;
    	for (int i = 1; i <= n; ++i)
    	{
    		cin >> a[i];
    		EL[++EL[0]] = a[i];
    	}
    	char ch;
    	for (int ar1, ar2, ar3, i = 1; i <= m; ++i)
    	{
    		cin >> ch >> ar1 >> ar2;
    		if (ch == 'Q')
    		{
    			cin >> ar3;
    			Op[i] = Operat(0, ar1, ar2, ar3);
    			continue;
    		}
    		Op[i] = Operat(1, ar1, 0, ar2);
    		EL[++EL[0]] = ar2;
    	}
    	sort(EL + 1, EL + 1 + EL[0]);
    	EL[0] = unique(EL + 1, EL + 1 + EL[0]) - EL - 1;
    	for (int tem, i = 1; i <= n; ++i)
    	{
    		tem = lower_bound(EL + 1, EL + 1 + EL[0], a[i]) - EL;
    		a[i] = tem;
    		BIT_Add(i, tem, +1);
    	}
    	for (int tem, i = 1; i <= m; ++i)
    	{
    		if (Op[i].t) // C x y
    		{
    			tem = lower_bound(EL + 1, EL + 1 + EL[0], Op[i].x) - EL;
    			BIT_Add(Op[i].l, a[Op[i].l], -1); // Notice !! a[] NOT a[i] orzrzrzrzrz
    			a[Op[i].l] = tem;
    			BIT_Add(Op[i].l, tem, +1);
    			continue;
    		}
    		// Q l r k
    		cout << EL[BIT_SumAndKth(Op[i].l, Op[i].r, Op[i].x)] << endl;
    	}
    	return 0;
    }
    


    整体二分


    Solution



    Code



    分块


    Solution



    Code


  • 相关阅读:
    第六天
    《分布式架构中数据一致性常见的几个问题》阅读心得
    第五天
    软件开发记录第四天
    资料整理
    Mongodb_分片集群模式
    MongoDB_spring整合mongodb
    安装环境
    MongoDB_副本集集群模式
    MongoDB_java连接MongoDB
  • 原文地址:https://www.cnblogs.com/ccryolitecc/p/13765570.html
Copyright © 2020-2023  润新知