• 初识线段树


    今天算是见到了线段树这玩意儿了,,,

    这个线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b]。每一个叶子节点表示了一个单位区间。对于每一个非叶结点所表示的结点[a,b],其左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。
    这个线段树可以使用指针来表示,也可以使用静态全局数组模拟(大小一般要开成节点的四倍哟O(∩_∩)O~)。
    其题目单节点更新、成端更新(需要用到延迟标记)、区间合并、扫描线。
    其常见操作如下:建立线段树(build)、更新操作(update)、查询操作(query)、向上回溯(pushup)、向下延时更新(pushdown),若要使用线段树,这几个模块化的函数可要记牢哟。(具体如何编写可参考下面的题目)
    再来看看今天做到的几道简单的线段树问题,完全没用到更新、向上回溯与向下延时更新。。。写起来还是比较简单的,就是要注意细节,不然调半天。。。
    hdoj1754 I hate it
    题意大概就是给了些成绩,然后去查找区间内最高分或者更新某一个成绩。
    思路很简单,直接使用build与query就行了,下面贴出代码:
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxx 200005
    #define l(u) (u<<1)
    #define r(u) (u<<1|1)
    using namespace std;
    int n,m,cj[200005],j,b,ans;
    struct data{
    	int l,r,sum;
    }a[maxx<<2];
    char c;
    void build(int x,int l,int r)
    {
    	a[x].l=l;a[x].r=r;
    	if(l==r)
    	{
    		a[x].sum=cj[l];
    		return ;
    	}
    	int mid=(r+l)/2;
    	build(l(x),l,mid);
    	build(r(x),mid+1,r);
    	a[x].sum=max(a[l(x)].sum,a[r(x)].sum);
    }
    void update(int x,int l,int r)
    {
    	if(a[x].l==a[x].r)
    	{
    		a[x].sum=r;
    		return ;
    	}
    	int mid=(a[x].r+a[x].l)/2;
    	if(l<=mid)update(l(x),l,r);
    	else update(r(x),l,r);
    	a[x].sum=max(a[l(x)].sum,a[r(x)].sum);
    }
    int cz(int x,int l,int r)
    {
    	if(a[x].l==l&&a[x].r==r)
    		return a[x].sum;
    	int mid=(a[x].r+a[x].l)>>1;
    	if(r<=mid) return cz(l(x),l,r);
    	else if(l>=mid+1)return cz(r(x),l,r);
    	else return max(cz(l(x),l,mid),cz(r(x),mid+1,r));
    }
    int main()
    {
    	freopen("e.in","r",stdin);
    	freopen("e.out","w",stdout);
    	while(scanf("%d%d",&n,&m)==2)
    	{
    		for (int i=1;i<=n;i++)
    		scanf("%d",&cj[i]);
    		build(1,1,n);
    		for(int i=1;i<=m;i++)
    		{
    			cin>>c>>j>>b;
    			if(c=='Q')
    			{
    				int ans=cz(1,j,b);
    				cout<<ans<<endl;
    			}
    			if(c=='U')
    			{
    				update(1,j,b);
    			}
    		}
    	}
    	return 0;	
    }
    

      poj3264 balanced lineup

    题意简言之就是求一个区间内牛的最大高度差,直接给代码吧,自行理解:

    #include <stdio.h>
    #define M 50005
    
    struct data
    {
        int l,r;
        int tall,shor;
    }line[3*M];
    int num[M];
    int min (int a,int b)
    {
        return a > b?b:a;
    }
    int max (int a,int b)
    {
        return a > b?a:b;
    }
    int low,hei;
    void BuildTree(int left,int right,int u)
    {
        line[u].l = left;
        line[u].r = right;
        if (line[u].l == line[u].r)
        {
            line[u].tall = num[left];
            line[u].shor = num[left];
            return ;
        }
        int mid = (line[u].l+line[u].r)/2;
        BuildTree(left,mid,2*u);
        BuildTree(mid+1,right,2*u+1);
        line[u].tall = max (line[2*u].tall,line[2*u+1].tall);
        line[u].shor = min (line[2*u].shor,line[2*u+1].shor);
       
    }
    void query (int left,int right,int u)
    {
        if (line[u].l == left&&line[u].r == right)
        {
            low = min (low,line[u].shor);
            hei = max (hei,line[u].tall);
            return ;
        }
        int mid = (line[u].l + line[u].r)/2;
        if (right <= mid)
            query (left,right,2*u);
        else if (left >= mid + 1)
            query (left,right,2*u+1);
        else
        {
            query(left,mid,2*u);
            query (mid+1,right,2*u+1);
        }
    }
    int main ()
    {
        int n,m,a,b;
        scanf ("%d%d",&n,&m);
        for (int i = 1;i <= n;i ++)
            scanf ("%d",&num[i]);
        BuildTree(1,n,1);
        while (m --)
        {
            scanf ("%d%d",&a,&b);
            low = 1000001;
            hei = 0;
            query (a,b,1);
            printf ("%d\n",hei - low);
        }
        return 0;
    }
    

      清清正正射命丸文是也~

  • 相关阅读:
    SQL 函数、存储过程、游标与事务模板
    JS给Element添加方法
    检测当前浏览器是否启用JS,Cookie
    Android 电量测试以及电量优化
    [转载]百度免费的文本编辑器Ueditor的使用说明
    sql 常用信息
    vs2010智能提示消失的解决办法
    IIS未能加载文件或程序集“System.Data.SQLite”或它的某一个依赖项
    智能的产生
    C#日期格式化
  • 原文地址:https://www.cnblogs.com/Ayateriteri/p/5667377.html
Copyright © 2020-2023  润新知