首页 > 其他分享 >笛卡尔树

笛卡尔树

时间:2024-09-23 20:01:04浏览次数:6  
标签:rt node return 笛卡尔 int -- lt

思路

如果说给你一个数组,有 \(q\) 组询问,询问一个区间的区间和,那么有最原始的做法。维护一个左端点和一个右端点,每次一位一位移动断点,那么时间复杂度是 \(n \times q\),那么如果我们将查询存起来,按一种我们想要的顺序去做呢?我们就可以排序,排序规则就是:

B = sqrt(n);
bool cmp(node _x, node _y) {
  if (_x.l / B != _y.l / B) {
    return _x.l / B < _y.l / B;
  }
  return _x.r < _y.r;
}

具体来说就是先将左端点分成一个一个的块,右端点则按从小到大排序即可。

时间复杂度

左端点在一个块内做多移动 \(n\) 次(|1,3,5,4,2|数字表示顺序),那么有 \(\sqrt{n}\) 的块,那就最多移动 \(n\times\sqrt{n}\)次
右端点也是一样
那么时间复杂度就是 \(O(2\timesn\times\sqrt{n})\)
code:

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 2e5 + 5, B = 455;

struct node {
	int l, r, id;
}a[N];

int n, q, x[N], ans[N];

bool cmp(node _x, node _y) {
	if (_x.l / B != _y.l / B) {
		return _x.l / B < _y.l / B;
	}
	return _x.r < _y.r;
}

signed main() {
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		cin >> x[i];
	}
	for (int i = 1; i <= q; i++) {
		cin >> a[i].l >> a[i].r;
		a[i].id = i; 
	}
	sort(a + 1, a + q + 1, cmp);
	for (int i = 1, lt = 1, rt = 1, tmp = x[1]; i <= q; i++) {
		while (lt < a[i].l) {				
			tmp -= x[lt];		
		  lt++;
		}
		while (rt < a[i].r) {				  
			rt++;		
		  tmp += x[rt];		
		}
		while (lt > a[i].l) {			
		  lt--;
			tmp += x[lt];
		}
		while (rt > a[i].r) {
			tmp -= x[rt];
			rt--;
		}
		ans[a[i].id] = tmp;
	}
	for (int i = 1; i <= q; i++) {
		cout << ans[i] << "\n";
	}
	return 0;
} 

优势

如:做算区间内有多少种颜色时极其方便

劣势

如:时间复杂度很劣,远远没有线段树优秀

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5, B = 455;

struct node {
	int l, r, id;
}a[N];

int n, q, x[N], ans[N], cnt = 0, mp[N + 5];

vector<int> v;

bool cmp(node _x, node _y) {
	if (_x.l / B != _y.l / B) {
		return _x.l / B < _y.l / B;
	}
	return _x.r < _y.r;
}

void check(int u, int op) {
	if (op == 1) {
		if (!mp[u]) {
			cnt++;
		}
		mp[u]++;
	}
	else {
		mp[u]--;
		if (!mp[u]) {
			cnt--;
		}
	}
}

int main() {
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		cin >> x[i];
		v.push_back(x[i]); 
	}
	sort(v.begin(), v.end());
	for (int i = 1; i <= n; i++) {
		x[i] = lower_bound(v.begin(), v.end(), x[i]) - v.begin(); 
	}
	for (int i = 1; i <= q; i++) {
		cin >> a[i].l >> a[i].r;
		a[i].id = i; 
	}
	sort(a + 1, a + q + 1, cmp);
	for (int i = 1, lt = 1, rt = 0; i <= q; i++) {
		while (lt < a[i].l) {				
			check(x[lt], -1);	
		  lt++;
		}
		while (rt < a[i].r) {				  
			rt++;	
			check(x[rt], 1);		
		}
		while (lt > a[i].l) {			
		  lt--;
			check(x[lt], 1);
		}
		while (rt > a[i].r) {
			check(x[rt], -1);
			rt--;
		}
		ans[a[i].id] = cnt;
	}
	for (int i = 1; i <= q; i++) {
		cout << ans[i] << "\n";
	}
	return 0;
} 

标签:rt,node,return,笛卡尔,int,--,lt
From: https://www.cnblogs.com/libohan/p/18427787

相关文章

  • 笛卡尔坐标张量简介7
    张量(tensor)这一术语最初是用来描述弹性介质各点应力状态的,后来发展成为力学和物理学的一个有力数学工具,目前力学方面的理论性文献都不同程度地这用了这一工具由坐标原点和三条不共面的标架直线构成的坐标系称为直线坐标系,如果三标架直线上的单位尺度相同,称为笛卡尔坐标系,否则称......
  • 【重学 MySQL】二十四、笛卡尔积的错误和正确的多表查询
    【重学MySQL】二十四、笛卡尔积的错误和正确的多表查询笛卡尔积的理解和错误笛卡尔积的理解定义例子在数据库中的应用总结笛卡尔积的错误正确的多表查询使用INNERJOIN使用WHERE子句(隐式内连接)总结在数据库查询中,特别是涉及到多表查询时,理解笛卡尔......
  • 笛卡尔树
    解决的问题有\(n\)个值,每个值有两个信息\((a_i,b_i)\)。你需要在这\(n\)个值间连边并形成一棵二叉树,使得:每个点的\(a_i\)满足二叉搜索树的性质。即对于所有\(v\in\text{subtree}_{lson}\)都有\(a_v\lea_u\),对于所有\(v\in\text{subtree}_{rson}\)都有\(a_v......
  • 笛卡尔树
    讲义 第1题   笛卡尔树一、定义与性质    笛卡尔树是一种特殊的二叉树数据结构,每个节点都由一对键值构成,即(k,w),其中k满足二叉搜索树的性质,而w满足堆的性质。具体来说:    二叉搜索树性质:      对于任意节点x,其左子树中的所有键值k都小于x......
  • 【数据结构】【模板】笛卡尔树
    笛卡尔树定义笛卡尔树每个节点有两种属性,一种是键值,一种是优先级。一般将位置作为键值,维护BST的性质,这样其中序遍历一定为\(1~n\)。一般将数值看作优先级,维护堆的性质。构建思路维护一个单调栈,表示现在的右链长度。我们将数组从前往后插入笛卡尔树。对于第\(i\)个......
  • 【Python】笛卡尔积 intertools.product()
    一、题目Thistoolcomputesthecartesianproductofinputiterables.Itisequivalenttonestedfor-loops.Forexample,product(A,B)returnsthesameas((x,y)forxinAfroyinB).SampleCodefromitertoolsimportproductprint(list(product([1,2,3],......
  • 理解笛卡尔积在数据库查询中的实际应用与优化
    理解笛卡尔积在数据库查询中的实际应用与优化大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!笛卡尔积是关系数据库查询中的一个基础概念,它描述了两个表之间所有可能的行组合。尽管它在某些情况下是必要的,但它也可能导致性能问题。本文将详细介绍笛卡......
  • 笛卡尔坐标转经纬度坐标
    functionfromCartesian(cartesian){constoneOverRadii={x:1.0/6378137.0,y:1.0/6378137.0,z:1.0/6356752.3142451793};constoneOverRadiiSquared={x:1.0/(6378137.0*6378137.0),y:1.0/(6378137.0*6378137.0),......
  • 经纬度坐标转笛卡尔坐标
    functionfromDegrees(longitude,latitude,height=0.0){longitude=(longitude*Math.PI)/180.0;latitude=(latitude*Math.PI)/180.0;constradiiSquared={x:6378137.0*6378137.0,y:6378137.0*6378137.0,z:6356752.31424517......
  • 笛卡尔树
    笛卡尔树:笛卡尔树是关于多个二元组\((k_i,w_i)\)的一棵树,使其所有\(k\)值满足二叉搜索树的性质,且所有\(w\)值都满足小根堆的性质。笛卡尔树有一些关于区间最值的美好性质,常常用于处理关于区间最值的问题。构建方法:在构建时,对于右链上的元素,自底向上一定是\(w\)值由小......