4.4学习总结

发布于:2024-04-06 ⋅ 阅读:(90) ⋅ 点赞:(0)

一.线段树概念

一.定义:

   线段树是一种二叉搜索树,而二叉搜索树,首先满足二叉树,即每个结点最多有两颗子树,并且是一颗搜索树,我们要知道,线段树的每个结点都存储了一个区间,也可以理解成一个线段,而搜索,就是在这些线段上进行搜索操作得到你想要的答案

(线段树的适用范围很广,可以在线维护修改以及查询区间上的最值求和。对于线段树来说,每次更新以及查询的时间复杂度为O(logN))

二.线段树操作思路

   线段树主要是把一段大区间 平均地划分 成两段小区间进行维护,再用小区间的值来更新大区间。这样既能保证正确性,又能使时间保持在 log ⁡ 级别(因为这棵线段树是平衡的)。也就是说一个[L,R]区间会被划分为两个区间分别是[L,(L+R)/2]和[(L+R)/2+1,R]这两个小区间。然后再递归下去分直达L=R。

二.线段树具体操作

一.建树

建树时每次递归就要先判断l是否等于r,等于就说明是叶子节点,也就是区间是[l,l],直接赋值a[l]/a[r],再返回。否则就递归构造左儿子结点和递归构造右儿子结点,最后更新父节点

void build(ll p,ll l,ll r)
{
	ll tl = p * 2, tr = p * 2 + 1;
	tree[p] = { l,r,ans[l],0 };
	if (l == r)
		return;
	ll mid = (l + r) / 2;
	build(tl, l, mid);
	build(tr, mid + 1, r);
	pushup(p);
}

二.区间修改

1.如果当前区间完全被覆盖在目标区间里将这个区间sum数组的的位置加上(r-l+1)*C

2.如果没有完全覆盖则先下传懒标记

3.如果这个区间的左孩子和目标区间有交集,那么就递归给左孩子分配任务

4.如果这个区间的右孩子和目标区间有交集,则递归分配任务给右孩子。

懒标记:(即在需要使用的时候在取值,否则存在父亲处)

//向上更新总和
void pushup(ll p)
{
	ll tl = p * 2, tr = p * 2 + 1;
	tree[p].sum = tree[tl].sum + tree[tr].sum;
}
//向下更新懒标记
void pushdown(ll p)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (tree[p].add)
	{
		tree[tl].sum += (tree[tl].r - tree[tl].l + 1) * tree[p].add;
		tree[tr].sum += (tree[tr].r - tree[tr].l + 1) * tree[p].add;
		tree[tl].add += tree[p].add;
		tree[tr].add += tree[p].add;
		tree[p].add = 0;
	}
}
//区间修改
void update(ll p,ll x,ll y,ll k)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (x <= tree[p].l && tree[p].r <= y) {
		tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
		tree[p].add += k;
		return;
	}
	ll mid = (tree[p].l + tree[p].r) / 2;
	pushdown(p);
	if (x <= mid)
		update(tl, x, y, k);
	if (y > mid)
		update(tr, x, y, k);
	pushup(p);
}

三.区间查询

1.如果当前区间完全被覆盖在目标区间里将对于sum位置的数据返回

2.如果没有完全覆盖则先下传懒标记

3.如果这个区间的左孩子和目标区间有交集,那么就递归给左孩子分配任务

4.如果这个区间的右孩子和目标区间有交集,则递归分配任务给右孩子。

ll query(ll p, ll x, ll y)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (x <= tree[p].l && tree[p].r <= y)
		return tree[p].sum;
	ll mid = (tree[p].l+tree[p].r) / 2;
	pushdown(p);
	ll sum = 0;
	if (x <= mid)
		sum += query(tl, x, y);
	if (y > mid)
		sum += query(tr, x, y);
	return sum;
}

 

三.例题分析

线段树的模版题,熟练掌握区间修改和区间查询即可,注意数据范围,要开long long

#include<iostream>
#include <stdio.h>
#include<set>
#include<map>
#include<string>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<vector>
using namespace std;
#define N 1000005
typedef long long ll;
int n, m, cnt;
int ans[N];
struct node {
	ll l, r, sum, add;
}tree[N*4];

void pushup(ll p)
{
	ll tl = p * 2, tr = p * 2 + 1;
	tree[p].sum = tree[tl].sum + tree[tr].sum;
}

void pushdown(ll p)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (tree[p].add)
	{
		tree[tl].sum += (tree[tl].r - tree[tl].l + 1) * tree[p].add;
		tree[tr].sum += (tree[tr].r - tree[tr].l + 1) * tree[p].add;
		tree[tl].add += tree[p].add;
		tree[tr].add += tree[p].add;
		tree[p].add = 0;
	}
}

void build(ll p,ll l,ll r)
{
	ll tl = p * 2, tr = p * 2 + 1;
	tree[p] = { l,r,ans[l],0 };
	if (l == r)
		return;
	ll mid = (l + r) / 2;
	build(tl, l, mid);
	build(tr, mid + 1, r);
	pushup(p);
}

ll query(ll p, ll x, ll y)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (x <= tree[p].l && tree[p].r <= y)
		return tree[p].sum;
	ll mid = (tree[p].l+tree[p].r) / 2;
	pushdown(p);
	ll sum = 0;
	if (x <= mid)
		sum += query(tl, x, y);
	if (y > mid)
		sum += query(tr, x, y);
	return sum;
}

void update(ll p,ll x,ll y,ll k)
{
	ll tl = p * 2, tr = p * 2 + 1;
	if (x <= tree[p].l && tree[p].r <= y) {
		tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
		tree[p].add += k;
		return;
	}
	ll mid = (tree[p].l + tree[p].r) / 2;
	pushdown(p);
	if (x <= mid)
		update(tl, x, y, k);
	if (y > mid)
		update(tr, x, y, k);
	pushup(p);
}
int main()
{
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%lld", &ans[i]);
	build(1, 1, n);
	while (m--)
	{
		char s;
		ll choice, x, y, z;
		cin >> s;
		if (s == 'C') {
			scanf("%lld%lld%lld", &x, &y, &z);
			update(1,x,y,z);
		}
		if (s == 'Q') {
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", query(1, x, y));
		}
	}
	return 0;
}

二.JDBC学习

刚开始接触mysql和JDBC的知识,初步学习其相关特点

实例演示

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class jdbc {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取连接
        String upl="jdbc:mysql://localhost:3306/chat";
        String username="root";
        String password="wei1810335767";
        Connection conn= DriverManager.getConnection(upl,username,password);

        //3.定义sql
        String sql="update user set sex='k' where id=1";

        //4.获取执行sql对象Statement
        Statement stat = conn.createStatement();

        //5.执行sql
        int i = stat.executeUpdate(sql);

        //6.处理结果
        System.out.println(i);

        //7.释放资源
        stat.close();
        conn.close();
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到