树套树P3380

开O2过了

cpp 复制代码
#include <iostream>
#include <istream>
#include <sstream>
#include <vector>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <ctime>
#include <cmath>
#include <cctype>
#include <string>
#include <cstdio>
#include <iomanip>


#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iterator>
#include <random>
using namespace std;


inline int read(int& x) {
	char ch = getchar();
	int f = 1; x = 0;
	while (ch > '9' || ch < '0') { if (ch == '-')f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); }
	return x * f;
}
//void ReadFile() {
//	FILE* stream1;
//	freopen_s(&stream1,"in.txt", "r", stdin);
//	freopen_s(&stream1,"out.txt", "w", stdout);
//}

static auto speedup = []() {ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); return nullptr; }();


template <class _Type>
class AVL
{
public:
	template <class _T>
	struct AVLNode {
		//AVLNode(_T input) :l(nullptr), r(nullptr), h(1), data(input) {}
		AVLNode() :data(), l(nullptr), r(nullptr), h(1), c(1), sub(1) {}
		_T data;
		AVLNode* l, * r;
		int h, c, sub;//高度 副本个数 子树节点个数
	};
	typedef AVLNode<_Type>  value_Type;
	typedef AVLNode<_Type>* point;
public:
	AVL() :m_root(nullptr), m_tot(0) {}
	~AVL() { clear(m_root); }
public:
	typename AVL<_Type>::point GetNode(_Type&& input);

	int  GetHight(typename AVL<_Type>::point node) {
		if (node == nullptr) return 0;
		return node->h;
	}
	int  GetSubCnt(typename AVL<_Type>::point node) {
		if (node == nullptr) return 0;
		return node->sub;
	}
	void flush(typename AVL<_Type>::point node) {
		if (node == nullptr) return;
		node->h = max(GetHight(node->l), GetHight(node->r)) + 1;
		node->sub = GetSubCnt(node->l) + GetSubCnt(node->r) + node->c;
	}
public:
	typename AVL<_Type>::point insert(_Type input);//插入
	typename AVL<_Type>::point _insert(typename AVL<_Type>::point cur, _Type&& input);

	void remove(_Type input);//删除
	typename AVL<_Type>::point _remove(typename AVL<_Type>::point cur, _Type&& input);

	typename AVL<_Type>::point findKth(int k);	//查找第k大
	int findRank(_Type x);
	typename AVL<_Type>::point findPre(_Type x);	//查找x前驱
	typename AVL<_Type>::point findNext(_Type x);//查找x后继
	typename AVL<_Type>::point find(_Type x);//查找x

public:
	void  rotate_left(typename AVL<_Type>::point& input);	//左旋转
	void  rotate_right(typename AVL<_Type>::point& input);	//右旋转
	typename AVL<_Type>::point revise(typename AVL<_Type>::point& node);//修正
	void clear(typename AVL<_Type>::point& input);
	void print(typename AVL<_Type>::point& input) {
		if (input == nullptr) return;
		print(input->l);
		m_data.insert(m_data.end(), input->c, input->data);
		cout << input->data << " ";
		print(input->r);
	}
public:
	typename AVL<_Type>::point   m_root;
	typename AVL<_Type>::point   m_new;//最后一个新增节点
	int		m_tot;//总节点个数
	vector<_Type> m_data;
};

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::GetNode(_Type&& input) {
	AVL<_Type>::point ret = new AVL<_Type>::value_Type();
	if (ret)ret->data = input, m_tot++;
	return m_new = ret;
}

template <class _Type>
void AVL<_Type>::clear(typename AVL<_Type>::point& input) {
	if (input == nullptr) return;
	clear(input->l);
	clear(input->r);
	input->l = nullptr;
	input->r = nullptr;
	input = nullptr;
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::insert(_Type input)//插入
{
	m_new = nullptr;
	m_root = _insert(m_root, std::forward<_Type>(input));
	return m_new;
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::_insert(typename AVL<_Type>::point p, _Type&& input)//插入
{
	//找到节点位置
	if (p == nullptr) return GetNode(std::forward<_Type>(input));

	//相同元素 标记数量
	if (p->data == input) {
		p->c++;
		p->sub++;
		return p;
	}
	if (p->data > input)p->l = _insert(p->l, std::forward<_Type>(input));
	else p->r = _insert(p->r, std::forward<_Type>(input));

	return revise(p);
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::revise(typename AVL<_Type>::point& p) {
	if (p == nullptr) return p;
	int hl = GetHight(p->l), hr = GetHight(p->r), diff = hl - hr;
	if (diff > 1) {
		//LL
		if (GetHight(p->l->l) >= GetHight(p->l->r)) {
			rotate_right(p);
		}
		else {
			//LR
			rotate_left(p->l);
			rotate_right(p);
		}
	}
	else if (diff < -1) {
		//RL
		if (GetHight(p->r->l) >= GetHight(p->r->r)) {
			rotate_right(p->r);
			rotate_left(p);
		}
		else rotate_left(p);//RR
	}
	flush(p);
	return p;
}

template <class _Type>
void AVL<_Type>::remove(_Type input)//删除
{
	m_root = _remove(m_root, std::forward<_Type>(input));
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::_remove(typename AVL<_Type>::point p, _Type&& input)
{
	if (p == nullptr) return p;
	if (p->data > input) {
		p->l = _remove(p->l, std::forward<_Type>(input));
	}
	else if (p->data < input) {
		p->r = _remove(p->r, std::forward<_Type>(input));
	}
	else {
		//已找到节点 有多个副本
		if (--p->c > 0) { m_tot--; return revise(p); }
		else {
			//有左右子树
			if (p->l && p->r) {
				//寻找前驱节点 一定有前驱和后继
				AVL<_Type>::point preplace = p->l;
				while (preplace->r) preplace = preplace->r;
				//交换数据
				swap(p->data, preplace->data);
				//副本数量
				swap(p->c, preplace->c);

				p->l = _remove(p->l, std::forward<_Type>(input));
			}
			else {
				m_tot--;
				AVL<_Type>::point preplace = p->l ? p->l : p->r;
				delete p;
				return preplace;
			}
		}
	}
	return revise(p);
}

template <class _Type>
void  AVL<_Type>::rotate_left(typename AVL<_Type>::point& node)//旋转
{
	if (node == nullptr || node->r == nullptr) return;
	AVL::point r = node->r;
	AVL::point rl = r->l;
	r->l = node;
	node->r = rl;
	node = r;

	flush(node->l);
	flush(node);
}

template <class _Type>
void  AVL<_Type>::rotate_right(typename AVL<_Type>::point& node)//右旋转
{
	if (node == nullptr || node->l == nullptr) return;
	AVL::point l = node->l;
	AVL::point lr = l->r;
	l->r = node;
	node->l = lr;
	node = l;
	flush(node->r);
	flush(node);
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::findKth(int k)	//查找第k大
{
	if (m_root == nullptr || k > m_tot) return nullptr;
	AVL<_Type>::point cur = m_root;
	while (cur) {
		int l = GetSubCnt(cur->l);
		int r = GetSubCnt(cur->r);
		int m = cur->c;
		if (k <= l) {
			cur = cur->l;
		}
		else if (k <= l + m) {
			return cur;
		}
		else {
			k -= l + m;
			cur = cur->r;
		}
	}
	return nullptr;
}

template <class _Type>
int AVL<_Type>::findRank(_Type x) {
	AVL<_Type>::point cur = m_root;

	int ans = 0;
	while (cur) {
		if (cur->data > x) {
			cur = cur->l;
		}
		else if (cur->data < x) {
			ans += GetSubCnt(cur->l) + cur->c;
			cur = cur->r;
		}
		else break;
	}
	if (cur == nullptr) return ans + 1;
	return ans + GetSubCnt(cur->l) + 1;
}


template <class _Type>
typename AVL<_Type>::point AVL<_Type>::findPre(_Type x)	//查找x前驱
{
	AVL<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data < x)ret = cur, cur = cur->r;
		else cur = cur->l;
	}
	return ret;
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::findNext(_Type x)//查找x后继
{
	AVL<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data > x)ret = cur, cur = cur->l;
		else cur = cur->r;
	}
	return ret;
}

template <class _Type>
typename AVL<_Type>::point AVL<_Type>::find(_Type x)//查找x
{
	AVL<_Type>::point cur = m_root;
	while (cur) {
		if (cur->data == x) return cur;
		else if (cur->data > x) cur = cur->l;
		else cur = cur->r;
	}
	return nullptr;
}



template <typename _Type>
class Splay {
private:
	template <typename _T>
	struct SplayNode {
		SplayNode() :data(), l(nullptr), r(nullptr), fa(nullptr), c(1), sub(1) {}
		_T data;
		SplayNode* l, * r, * fa;
		int c, sub;//副本个数 子树节点个数
	};
public:
	typedef SplayNode<_Type>  value_Type;
	typedef SplayNode<_Type>* point;
public:
	Splay() :m_root(nullptr), m_tot(0) {}
	~Splay() { clear(m_root); }
	void clear(typename Splay<_Type>::point& input);
public:
	int  GetSubCnt(typename Splay<_Type>::point node) {
		if (node == nullptr) return 0;
		return node->sub;
	}
	void flush(typename Splay<_Type>::point node) {
		if (node == nullptr) return;
		node->sub = GetSubCnt(node->l) + GetSubCnt(node->r) + node->c;
	}
	typename Splay<_Type>::point GetNode(_Type&& input);
public:
	typename Splay<_Type>::point insert(_Type input);//插入
	void remove(_Type input);//删除
	typename Splay<_Type>::point find(_Type x);//查找x
	typename Splay<_Type>::point splay(typename  Splay<_Type>::point& input, typename  Splay<_Type>::point target = nullptr);//
	typename Splay<_Type>::point findKth(int k);	//查找第k大
	int findRank(_Type x);
	typename Splay<_Type>::point findPre(_Type x);	//查找x前驱
	typename Splay<_Type>::point findNext(_Type x);//查找x后继
	void reverse(int l, int r);
public:
	void  rotate_left(typename  Splay<_Type>::point& input);	//左旋转
	void  rotate_right(typename Splay<_Type>::point& input);	//右旋转
private:
	typename Splay<_Type>::point   m_root;
	int m_tot;
};

//
template <class _Type>
typename Splay<_Type>::point Splay<_Type>::GetNode(_Type&& input) {
	Splay<_Type>::point ret = new Splay<_Type>::value_Type();
	if (ret)ret->data = input, m_tot++;
	return ret;
}
template <class _Type>
void Splay<_Type>::clear(typename Splay<_Type>::point& input) {
	if (input == nullptr) return;
	clear(input->l);
	clear(input->r);
	input->l = nullptr;
	input->r = nullptr;
	input = nullptr;
}

template <class _Type>
void Splay<_Type>::reverse(int l, int r)
{
	l = findKth(l);
	r = findKth(r + 2);
	Splay(l, 0);
	Splay(r, l);

}
template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findKth(int k)	//查找第k大
{
	if (m_root == nullptr || k > m_tot) return nullptr;
	Splay<_Type>::point cur = m_root;
	while (cur) {
		int l = GetSubCnt(cur->l);
		int r = GetSubCnt(cur->r);
		int m = cur->c;
		if (k <= l) {
			cur = cur->l;
		}
		else if (k <= l + m) {
			return splay(cur);
		}
		else {
			k -= l + m;
			cur = cur->r;
		}
	}
	return nullptr;
}

template <class _Type>
int Splay<_Type>::findRank(_Type x) {
	Splay<_Type>::point cur = m_root;

	int ans = 0;
	while (cur) {
		if (cur->data > x) {
			cur = cur->l;
		}
		else if (cur->data < x) {
			ans += GetSubCnt(cur->l) + cur->c;
			cur = cur->r;
		}
		else break;
	}
	if (cur == nullptr) return ans + 1;

	ans += GetSubCnt(cur->l) + 1;
	splay(cur);
	return ans;
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findPre(_Type x)	//查找x前驱
{
	Splay<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data < x)ret = cur, cur = cur->r;
		else cur = cur->l;
	}
	return splay(ret);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::findNext(_Type x)//查找x后继
{
	Splay<_Type>::point cur = m_root, ret = nullptr;
	while (cur) {
		if (cur->data > x)ret = cur, cur = cur->l;
		else cur = cur->r;
	}
	return splay(ret);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::find(_Type x)//查找x
{
	Splay<_Type>::point cur = m_root;
	while (cur) {
		if (cur->data == x) {
			break;
		}
		else if (cur->data > x) {
			cur = cur->l;
		}
		else {
			cur = cur->r;
		}
	}
	return splay(cur);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::insert(_Type input)//插入
{
	if (m_root == nullptr) return m_root = GetNode(std::forward<_Type>(input));
	else {
		Splay<_Type>::point cur = m_root;
		while (cur) {
			if (cur->data == input) {
				cur->c++;
				m_tot++;
				break;
			}
			else if (cur->data > input) {
				if (cur->l)cur = cur->l;
				else {
					cur->l = GetNode(std::forward<_Type>(input));
					cur->l->fa = cur;
					cur = cur->l;
					break;
				}
			}
			else {
				if (cur->r)cur = cur->r;
				else {
					cur->r = GetNode(std::forward<_Type>(input));
					cur->r->fa = cur;
					cur = cur->r;
					break;
				}
			}
		}
		return splay(cur);
	}
}

template <class _Type>
void Splay<_Type>::remove(_Type input)//删除
{
	Splay<_Type>::point p = find(input), l, r;
	if (p == nullptr) return;
	p = splay(p);
	if (--p->c > 0)return;

	if (p->l == nullptr) {
		m_root = p->r;
		if (p->r)p->r->fa = nullptr;
	}
	else if (p->r == nullptr) {
		m_root = p->l;
		if (p->l)p->l->fa = nullptr;
	}
	else {
		//分裂成2棵子树
		l = p->l;
		r = p->r;
		l->fa = r->fa = nullptr;

		m_root = l;
		l = findPre(p->data); //查找左子树的前驱 相当于左子树的最大值 没有右子树
		//合并2棵子树
		l->r = r;
		r->fa = l;
	}
	delete p;
	m_tot--;
	flush(m_root);
}

template <class _Type>
typename Splay<_Type>::point Splay<_Type>::splay(typename  Splay<_Type>::point& input, typename  Splay<_Type>::point target)
{
	if (input == nullptr) return nullptr;

	while (input->fa != target) {
		Splay<_Type>::point fa = input->fa, ffa = fa->fa;
		bool bol = fa->l == input;
		//父节点是目标节点
		if (ffa == target) {
			//左子树
			if (bol) rotate_right(fa);
			else rotate_left(fa);
		}
		else {
			bool bofl = ffa->l == fa;
			//LL
			if (bofl && bol) {
				rotate_right(ffa);
				rotate_right(fa);
			}
			else if (!bofl && !bol) {
				//RR
				rotate_left(ffa);
				rotate_left(fa);
			}
			else if (bofl && !bol) {
				//LR
				rotate_left(fa);
				rotate_right(ffa);
			}
			else {
				//RL
				rotate_right(fa);
				rotate_left(ffa);
			}
		}
	}
	if (target == nullptr)m_root = input;
	return input;
}

template <class _Type>
void  Splay<_Type>::rotate_left(typename Splay<_Type>::point& node)//左旋转
{
	if (node == nullptr || node->r == nullptr) return;
	Splay::point r = node->r;
	Splay::point rl = r->l;

	if (node->fa) {
		if (node->fa->l == node) node->fa->l = r;
		else node->fa->r = r;
	}
	r->fa = node->fa;
	node->fa = r;

	r->l = node;
	node->r = rl;
	if (rl)rl->fa = node;

	node = r;

	flush(node->l);
	flush(node);
}

template <class _Type>
void  Splay<_Type>::rotate_right(typename Splay<_Type>::point& node)//右旋转
{
	if (node == nullptr || node->l == nullptr) return;
	Splay::point l = node->l;
	Splay::point lr = l->r;

	if (node->fa) {
		if (node->fa->l == node) node->fa->l = l;
		else node->fa->r = l;
	}
	l->fa = node->fa;
	node->fa = l;

	l->r = node;
	node->l = lr;
	if (lr)lr->fa = node;

	node = l;
	flush(node->r);
	flush(node);
}


const int maxn = 5e4 + 7,INF = 2147483647;
int arr[maxn], n, m;

class segment {
public:
	typedef long long int ll;
	segment() {
		
	}
	void build(int l, int r, int idx) {
		for (int i = l; i <= r; i++) {
			root[idx].insert(arr[i]);
		}
		if (l == r) return;
		int mid = (l + r) >> 1;
		int lson = idx * 2, rson = lson + 1;
		build(l, mid, lson);
		build(mid + 1, r, rson);

	}


	void _modify(int l, int r, int idx, int cl, int cr, int x,int y) {
		if (l > cr || r < cl) return;
		root[idx].remove(arr[x]);
		root[idx].insert(y);
		if (l == r) return;

		int mid = (l + r) >> 1, lson = idx * 2, rson = lson + 1;

		if (mid >= cl) _modify(l, mid, lson, cl, cr, x,y);
		if (mid < cr) _modify(mid + 1, r, rson, cl, cr, x,y);

	}
	void modify(int x, int y) {
		_modify(1, n, 1, x, x,x, y);
		arr[x] = y;
	}

	int queryrank(int p, int l, int r, int cl,int cr,int k) // query the highest rank of value 'k'
	{	
		if (l > cr || r < cl) return 0;
		if (l >= cl && r <= cr) {
			return root[p].findRank(k) - 1;
		}
		
		int mid = (l + r) >> 1;
		
		return queryrank(p * 2, l,mid, cl, cr, k) + queryrank(p * 2 + 1,mid + 1,r, cl, cr, k);
	}

	int querynum(int u, int v, int k) // query the value of kth num
	{
		int l = 0, r = 1e8;
		while (l < r)
		{
			int mid = (l + r + 1) / 2;
			int c = queryrank(1, 1, n, u, v, mid);
			if (c < k)
				l = mid;
			else
				r = mid - 1;
		}
		return r;
	}
	int querypre(int p, int l, int r,int cl,int cr, int k)
	{
		if (l > cr || r < cl) return -INF;
			
		if (l >= cl && r <= cr) {
			AVL<int>::point ret = root[p].findPre(k);
			if(ret != nullptr)return ret->data;
			return -INF;
		}
		int mid = (l + r) >> 1;
		return max(querypre(p * 2, l,mid,cl, cr, k), querypre(p * 2 + 1,mid + 1,r, cl, cr, k));
	}
	int querysuf(int p, int l, int r,int cl,int cr, int k)
	{
		if (l > cr || r < cl)return INF;
			
		if (l >= cl && r <= cr) {
			AVL<int>::point ret = root[p].findNext(k);
			if(ret != nullptr)return ret->data;
			return INF;
		}
		int mid = (l + r) >> 1;
		return min(querysuf(p * 2,l,mid, cl, cr, k), querysuf(p * 2 + 1,mid + 1,r, cl, cr, k));
	}

public:
	AVL<int> root[maxn << 3];
};
segment tree;

int main()
{
	//ReadFile();
	read(n);
	read(m);
	for (int i = 1; i <= n; i++)
		read(arr[i]);

	tree.build(1, n,1);
	int opt, x, y;
	for (int i = 0; i < m; ++i)
	{
		read(opt);
		if (opt == 3)
		{
			read(x); read(y);
			tree.modify(x,y);
		}
		else
		{
			int l, r, k;
			read(l); read(r); read(k);
			if (opt == 1) printf("%d\n", tree.queryrank(1, 1, n, l, r, k) + 1);
			else if (opt == 2) printf("%d\n", tree.querynum(l, r, k));
			else if (opt == 4) printf("%d\n", tree.querypre(1, 1, n, l, r, k));
			else printf("%d\n", tree.querysuf(1, 1, n, l, r, k));
		}
	}
	return 0;
}
相关推荐
林开落L15 分钟前
前缀和算法习题篇(上)
c++·算法·leetcode
Prejudices28 分钟前
C++如何调用Python脚本
开发语言·c++·python
单音GG31 分钟前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
qing_0406031 小时前
C++——多态
开发语言·c++·多态
孙同学_1 小时前
【C++】—掌握STL vector 类:“Vector简介:动态数组的高效应用”
开发语言·c++
charlie1145141911 小时前
Qt Event事件系统小探2
c++·qt·拖放·事件系统
iiiiiankor1 小时前
C/C++内存管理 | new的机制 | 重载自己的operator new
java·c语言·c++
小辛学西嘎嘎1 小时前
C/C++精品项目之图床共享云存储(3):网络缓冲区类和main
c语言·开发语言·c++
c语言鹌鹑蛋2 小时前
C++初阶 --- 类和对象(1)
开发语言·c++
Jack黄从零学c++2 小时前
opencv(c++)图像的灰度转换
c++·人工智能·opencv