zoukankan      html  css  js  c++  java
  • 线段树技巧练习--GSS1

    GSS系列

    1: 给定序列(正负)求区间最大值

    题面:
    给n,n个数
    给m,m个询问 x,y
    输出(x,y)区间中的区间最大值

    线段树增加内容:lmax,rmax :左右最大
    dat :表示该段最大值

    部分代码

    udpate部分

    inline void update(int x) {
    	c[x].sum=c[lson(x)].sum+c[rson(x)].sum;
    	c[x].lmax=max(c[lson(x)].lmax,c[lson(x)].sum+c[rson(x)].lmax);
    	c[x].rmax=max(c[rson(x)].rmax,c[rson(x)].sum+c[lson(x)].rmax);
    	c[x].dat=max(max(c[lson(x)].dat,c[rson(x)].dat),c[lson(x)].rmax+c[rson(x)].lmax);
    }
    
    

    avatar

    蓝色为lmax,绿色为rmax
    结合图例和代码 想一想,为什么?

    build部分

    void build(int x,int l,int r) {
    	if (l==r) {
    		c[x].dat=c[x].sum=c[x].lmax=c[x].rmax=read();
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson(x),l,mid);
    	build(rson(x),mid+1,r);
    	update(x);
    	
    }
    
    

    较为有趣的是输入方式。

    query部分

    inline note query(int x,int l,int r,int ql,int qr) {
    	if (ql<=l&&qr>=r) return c[x];
    	int mid=(l+r)>>1;
    	if (ql>mid) return query(rson(x),mid+1,r,ql,qr);
    	if (qr<=mid) return query(lson(x),l,mid,ql,qr);
    	else {
    		note ans,a,b;
    		a=query(lson(x),l,mid,ql,qr);
    		b=query(rson(x),mid+1,r,ql,qr);
    		ans.sum=a.sum+b.sum;
    		ans.dat=max(a.dat,a.rmax+b.lmax);
    		ans.dat=max(ans.dat,b.dat);
    		ans.lmax=max(a.lmax,a.sum+b.lmax);
    		ans.rmax=max(b.rmax,b.sum+a.rmax);
    		return ans;
    		
    	}
    }
    
    

    此处返回值是一个note(线段树)型
    思想类似于普通线段树 懂得都懂:D

    可以了...
    贴一下源代码

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    
    #define M 500050 
    
    using namespace std;
    
    inline int read() {
    	int f=1,x=0;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){
    		if (ch=='-') f=-1;
    		ch=getchar();
    	}
    	while(ch<='9'&&ch>='0') 
    		x=x*10+ch-'0',ch=getchar();
    	return f*x;
    }
    
    int n,m;
    
    struct note {
    	int sum,lmax,rmax,dat;	
    }c[M<<2];
    
    inline int lson(int x) {return x<<1;}
    inline int rson(int x) {return x<<1|1;}
    
    inline void update(int x) {
    	c[x].sum=c[lson(x)].sum+c[rson(x)].sum;
    	c[x].lmax=max(c[lson(x)].lmax,c[lson(x)].sum+c[rson(x)].lmax);
    	c[x].rmax=max(c[rson(x)].rmax,c[rson(x)].sum+c[lson(x)].rmax);
    	c[x].dat=max(max(c[lson(x)].dat,c[rson(x)].dat),c[lson(x)].rmax+c[rson(x)].lmax);
    }
    
    void build(int x,int l,int r) {
    	if (l==r) {
    		c[x].dat=c[x].sum=c[x].lmax=c[x].rmax=read();
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson(x),l,mid);
    	build(rson(x),mid+1,r);
    	update(x);
    	
    }
    
    inline note query(int x,int l,int r,int ql,int qr) {
    	if (ql<=l&&qr>=r) return c[x];
    	int mid=(l+r)>>1;
    	if (ql>mid) return query(rson(x),mid+1,r,ql,qr);
    	if (qr<=mid) return query(lson(x),l,mid,ql,qr);
    	else {
    		note ans,a,b;
    		a=query(lson(x),l,mid,ql,qr);
    		b=query(rson(x),mid+1,r,ql,qr);
    		ans.sum=a.sum+b.sum;
    		ans.dat=max(a.dat,a.rmax+b.lmax);
    		ans.dat=max(ans.dat,b.dat);
    		ans.lmax=max(a.lmax,a.sum+b.lmax);
    		ans.rmax=max(b.rmax,b.sum+a.rmax);
    		return ans;
    		
    	}
    }
    
    int main() {
    	n=read();
    	build(1,1,n);
    	m=read();
    	int x,y;
    	for (int i=1;i<=m;i++) {
    		x=read();y=read();
    		printf("%d
    ",query(1,1,n,x,y).dat);
    	}
    	return 0;
    
    }
    

    溜了三( ᐛ )

  • 相关阅读:
    《程序员修炼之道——从小工到专家》读后感二
    2019.10.14课堂总结
    《程序员修炼之道——从小工到专家》读后感一
    2019.09.23课堂总结
    回文序列判断
    动手动脑
    2018/10/21动手动脑及类的创建
    动手动脑-java重载
    第二次上机实验体会
    Java第一次上机实验源代码
  • 原文地址:https://www.cnblogs.com/still-here-shining/p/14002277.html
Copyright © 2011-2022 走看看