首页 > 其他分享 >线段树(原理、构造和区间查询,例题:Balanced Lineup)

线段树(原理、构造和区间查询,例题:Balanced Lineup)

时间:2024-07-20 15:56:20浏览次数:9  
标签:pr 例题 int tree mid ans Balanced Lineup pl

概念

原理

       线段树是分治法和二叉树的结合,二叉树上的节点都是根据分治得到的。节点所表示的,也就是线段,可以是区间和、最值或者是其他的,,每次分治,左右子树各一半,每个节点的值代表了以它为根的子树上所有节点的值。通过线段树,大区间的解可以从小区间的解合并而来。

构造

令节点编号为p,指向区间[pl,pr],以求区间和为例(换成求最值或者其他也没有问题)。

代码:

struct t{
	int L;
	int R;
	int data;
}tree[N*4];

void build(int p,int pl,int pr) {
	tree[p].L = pl;
	tree[p].R = pr;
	if(pl == pr) {
		tree[p].data = input[pl];
		return;
	}
	int mid = (pl + pr)>>1;//分治 
    build(p * 2,pl,mid);//左子树
    build(p * 2 + 1,mid + 1,pr);//右子树
    tree[p].data = tree[p * 2].data + tree[p * 2 + 1].data;
}

区间查询

       不论是区间和还是最值或者其他,都可以通过线段树进行查询。比如一个一棵包含10个元素的线段树,当需要查询任意区间[L,R]的最小值时,假设寻找的是[2,5]的最小值,递归查询区间[2,2]、[3,3]、[4,5],就可以得到三个区间各自的最小值,然后再对它们求最小值,求和也是一样的道理。查询区间[L,R]的和,当查询到某个递归节点p时,会有两种情况:①[L,R]完全覆盖了[pl,pr],此时直接返回p的data值即可。②[L,R]与[pl,pr]部分重叠,分别搜索左右子节点。

代码:

int query(int L,int R,int p,int pl,int pr) {
	//完全覆盖 
	if(L <= pl && R >= pr) {
		return tree[p].data;
	}
	//部分覆盖 
	int mid = (pl + pr)>>1;
	int ans = 0;
	if(L <= mid) {
		ans += query(L,R,p * 2,pl,mid);
	}
	if(R > mid) {
		ans += query(L,R,p * 2 + 1,mid + 1,pr);
	}
	return ans;
}

例题

题目:

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 100,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.
Farmer John has made a list of Q (1 ≤ Q ≤ 30) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

输入:
Line 1: Two space-separated integers, N and Q.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i
Lines N+2..N+Q+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

输出:
Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

示例1:

输入:

6 3
1
7
3
4
2
5
1 5
4 6
2 2

输出:

6
3
0

思路:

本题其实也就是用到了上述线段树的思想,找出最大值与最小值进行求差。

代码:

#include<bits/stdc++.h>
using namespace std;

int tree1[400005];//最大值 
int tree2[400005];//最小值 

void build(int p,int pl,int pr)
{
    if(pl == pr)
    {
        cin >> tree1[p];
        tree2[p] = tree1[p];
        return;
    }
    int mid = (pl + pr) >> 1;
    build(p<<1,pl,mid);
    build(p<<1|1,mid + 1,pr);
    tree1[p] = max(tree1[p<<1],tree1[p<<1|1]);
    tree2[p] = min(tree2[p<<1],tree2[p<<1|1]);
}

int querymax(int L,int R,int p,int pl,int pr)//查询最大值 
{
    if(L <= pl && R >= pr) {
    	return tree1[p];
	}
    int mid = (pl + pr) >> 1;
    int ans=0;
    if(L <= mid) {
    	ans=max(ans,querymax(L,R,p<<1,pl,mid));	
	}
    if(R > mid) {
    	ans=max(ans,querymax(L,R,p<<1|1,mid + 1,pr));	
	}
    return ans;
}

int querymin(int L,int R,int p,int pl,int pr)//查询最小值 
{
    if(L <= pl && R >= pr) {
    	return tree2[p];
	}
    int mid = (pl + pr) >> 1;
    int ans=1000001;
    if(L <= mid) {
    	ans=min(ans,querymin(L,R,p<<1,pl,mid));	
	}
    if(R > mid) {
    	ans=min(ans,querymin(L,R,p<<1|1,mid + 1,pr));	
	}
    return ans;
}

int main()
{
    int n,m,s,e;
    cin >> n >> m;
    build(1,1,n);
    for(int i = 1; i <= m; i++)
    {
        cin >> s >> e;
        cout << querymax(s,e,1,1,n)-querymin(s,e,1,1,n) << endl;
    }
    return 0;
}

标签:pr,例题,int,tree,mid,ans,Balanced,Lineup,pl
From: https://blog.csdn.net/2301_77214603/article/details/140571024

相关文章

  • Imbalanced Arrays
    还没有仔细看官方题解和洛谷题解,重新做的时候看一下有没有什么可以吸收的说一下我的做法:首先看到第二个条件,不难想出\(i\)和\(-i\)只有可能选一个,此时观察样例,以及发现\(b\)刚好有\(n\)个数,所以不难想到最终\(b\)的构造方案是由\(1\)~\(n\)的每一个数或其相反数组成的,且每个数......
  • C语言典型例题7
    本系列博客针对于《C程序设计教程(第四版)——谭浩强编著》这本书中的所有例题和习题进行了详细的解释和学习,希望可以对你学习C语言可以有所帮助。有些代码可能会在前面详细解释,后面会一笔带过,希望大家可以多多翻阅,谢谢大家啦!!!嘻嘻!!!例题:求5!。//《C程序设计教程(第4版)——谭浩强......
  • 玄机——第九章-blueteam 的小心思 wp(HVV——“蓝队”应急响应简单模拟例题)
    文章目录一、前言二、概览简介三、参考文章四、步骤(解析)准备步骤#1.0步骤#1.1攻击者通过什么密码成功登录了网站的后台?提交密码字符串的小写md5值,格式flag{md5}。步骤#1.2攻击者在哪个PHP页面中成功上传了后门文件?例如upload.php页面,上传字符串"upload.php"的小写md5值......
  • Java二叉树经典例题
    目录一.相同的树二.翻转二叉树三.平衡二叉树四.对称二叉树五.根据前(后)和中序排序构建二叉树1.前序和中序构建2.后序和中序构建六.二叉树的层序遍历七.二叉树非递归遍历1.前序遍历2.中序遍历3.后序遍历八.总结前言:前面说过树是通过递归定义的。做二叉树的题,递......
  • 【c语言】函数递归的一些例题1.编写一个函数,不许创建临时变量,求字符串长度 2.求n的阶
    1.intmy_strlen(char*str){   if(*str!='\0')   {      return1+my_strlen(str+1);//利用递归求字符串长度:递归一次就是多一个字符这样就可以求出字符串的长度了   }   else      return0;}intmain(){   //编写......
  • 题解:SP11469 SUBSET - Balanced Cow Subsets
    SP11469(折半搜索)题目大意:给出$N$个数,求可以被分成两个和相等的集合的子集数。思路分析:首先考虑朴素的DFS,每个数有三种情况:选为$A$集合,选为$B$集合,两个集合都不选。暴力DFS时间复杂度为$3^{20}$。观察到$N$很小,而$3^{10}$是可以通过本题的,于是考虑折半搜索。我......
  • C语言典型例题
    本系列博客针对于《C程序设计教程(第四版)——谭浩强编著》这本书中的所有例题和习题进行了详细的解释和学习,希望可以对你学习C语言可以有所帮助。有些代码可能会在前面详细解释,后面会一笔带过,希望大家可以多多翻阅,谢谢大家啦!!!嘻嘻!!!//C程序设计教程(第四版)——谭浩强编著//例......
  • CF1237F Balanced Domino Placements
    比较有意思的Counting,想到横竖两种骨牌的独立性就很好做了考虑如果枚举最后放了\(x\)块横着的骨牌,\(y\)块竖着的骨牌,直接考虑它们的摆放不方便,不妨转化一下在所有空余的行中,选择\(x+2y\)行,且满足其中有\(y\)对相邻的行;在所有空余的列中,选择\(2x+y\)列,且满足其中有\(x......
  • [namespace hdk] Balanced_tree 整合
    代码#include<bits/stdc++.h>usingnamespacestd;namespacehdk{ namespacebalanced_tree{ constintN=2000001,inf=114514191; classsplay{ private: introot,tot; structtree{ intw; intcnt,size; intfa,son[2]; }t[N];......
  • 【DFS】深度优先搜索 洛谷选数例题讲解
    DFS深搜选数问题看一看题......