• 9.1


    线段树

    资料:
    https://blog.csdn.net/WhereIsHeroFrom/article/details/78969718

    https://www.cnblogs.com/cjyyb/p/8567674.html

    https://www.cnblogs.com/cjyyb/p/8567721.html

    P4145 上帝造题的七分钟2 / 花神游历各国

    /*
    translation:
    	第三行一个整数m,表示有m次操作。
        k=0表示给[l,r]中的每个数开平方(下取整)
        k=1表示询问[l,r]中各个数的和。
    	数据中有可能l>r所以遇到这种情况请交换l和r。
    solution:
    	唯一的考点,就是在如何取根号上,由于期间信息无法快速更新,所以无法使用延迟标记lazytag
    	(哦,这太可怕了QAQ),所以大家都注意到了10^9最多开5次就不变了,所以我们可以
    	考虑每次把修改暴力递归下去,直到当前区间已经全是0或1为止,然后return就好了。
    	似乎这题目前只有这一种解法,所以说不是非常的新鲜,本题解主要就是记录一种思想和历程,
    	学习一种结构,一定要搞清楚原理后再回头看看,有时候会柳暗花明又一村
    	喏 ,code is below.
    trigger:
    	“下去整 ” ,最最重要的优化就是maxx>1才change 
    	区间修改,区间查询,but,无结合律性质 
    note:
    	*暴力线段树 ,无法搞lazy_tag ,所以没有pushdown,f的操作 
    date:
    	2019.08.15
    	2019.09.01
    */
    #define lson o<<1
    #define rson o<<1|1
    
    #define N 1000005
    int n,m;
    int a[N];
    
    struct tree{
    	int l,r;
    	int sum,maxx;//maxx表示最高次幂 
    }t[N<<2];
    
    inline void pushup(int o){
    	t[o].sum=t[lson].sum+t[rson].sum;
    	t[o].maxx=max(t[lson].maxx,t[rson].maxx);
    }
    
    inline void build(int l,int r,int o){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].sum=t[o].maxx=a[l];
    		return ;
    	}
    	int mid=t[o].l+t[o].r>>1;
    	build(l,mid,lson);
    	build(mid+1,r,rson);
    	pushup(o);
    }
    
    inline void change(int o,int x,int y){
    	if(t[o].l==t[o].r){
    		t[o].sum=t[o].maxx=sqrt(t[o].sum);
    		return ;
    	}
    	int mid=t[o].l+t[o].r>>1;
    	if(x<=mid && t[lson].maxx>1)change(lson,x,y);
    	if(mid<y && t[rson].maxx>1)change(rson,x,y);
    	pushup(o);
    }
    
    inline int query(int o,int x,int y){
    	if(x<=t[o].l && t[o].r<=y){
    		return t[o].sum;
    	}
    	int ans=0;
    	int mid=t[o].l+t[o].r>>1;
    	if(x<=mid)ans+=query(lson,x,y);
    	if(mid<y)ans+=query(rson,x,y);
    	return ans; 
    }
    
    #undef int 
    int main(){
    #define int long long
    	freopen("huashen.txt","r",stdin);
    	rd(n);
    	rep(i,1,n)rd(a[i]);
        build(1,n,1);
        rd(m);
        while(m--){
        	int op,l,r;rd(op),rd(l),rd(r);
    		if(l>r)swap(l,r);
    		if(op==0)change(1,l,r);
    		else printf("%d
    ",query(1,l,r));
    	}
    	return 0;
    }
    

    线段树1 板子

    /*
    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    */
    #define lson o<<1
    #define rson o<<1|1
    
    #define N 100010
    
    int a[N];
    struct tree{
    	int l,r;
    	int sum,add;
    }t[N<<2];
    
    inline void pushup(int o){t[o].sum=t[lson].sum+t[rson].sum;}
    
    inline void f(int delta,int o){
    	t[o].add+=delta;
    	t[o].sum+=delta*(t[o].r-t[o].l+1);
    }
    
    inline void pushdown(int o){
    	if(t[o].add==0)return;
    	f(t[o].add,lson);
    	f(t[o].add,rson);
    	t[o].add=0;
    }
    
    inline void update(int o,int x,int y,int k){
    	if(x<=t[o].l && t[o].r<=y){
    		f(k,o);
    		return ;
    	}
    	pushdown(o);
    	int mid=t[o].l+t[o].r>>1;
    	if(x<=mid)update(lson,x,y,k);
    	if(mid<y)update(rson,x,y,k);
    	pushup(o);
    }
    
    inline int query(int o,int x,int y){
    	if(x<=t[o].l && t[o].r<=y){
    		return t[o].sum;
    	}
    	pushdown(o);
    	int mid=t[o].l+t[o].r>>1;
    	int ans=0;
    	if(x<=mid)ans+=query(lson,x,y);
    	if(mid<y)ans+=query(rson,x,y);
    	return ans;
    }
    
    inline void build(int l,int r,int o){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].sum=a[l];
    		return ;
    	}
    	int mid=l+r>>1;
    	build(l,mid,lson);
    	build(mid+1,r,rson);
    	pushup(o);
    }
    
    
    #undef int
    int main(){
    #define int long long
    	//freopen("sgm1.txt","r",stdin);
        int n,m;rd(n),rd(m);
        rep(i,1,n)rd(a[i]);
        build(1,n,1);
        while(m--){
        	char op[3];
        	int x,y,k;
        	cin>>op;
        	if(op[0]=='C'){
        		rd(x),rd(y),rd(k);
        		update(1,x,y,k);
    		}
    		else if(op[0]=='Q'){
    			rd(x),rd(y);
    			printf("%lld
    ",query(1,x,y));
    		}
    	}
        return 0;
    }
    

    区间最大连续子段和

    #define lson o<<1
    #define rson o<<1|1
    
    #define N 500001
    
    int max_3(int a,int b,int c){
    	int d=a;
    	if(b>d)d=b;
    	if(c>d)d=c;
    	return d;
    }
    
    struct tree{
        int l,r;
        int lmax,rmax,sum,dat;
    }t[N<<2];
    
    inline void pushup(int o){
    	t[o].lmax=max_3(t[lson].sum,t[lson].sum+t[rson].lmax,t[lson].lmax);
    	t[o].rmax=max_3(t[rson].sum,t[rson].sum+t[lson].rmax,t[rson].rmax);
    	t[o].dat=max_3(t[lson].dat,t[rson].dat,t[lson].rmax+t[rson].lmax);
    	t[o].sum=t[lson].sum+t[rson].sum;
    }
    
    inline void build(int l,int r,int o){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		rd(t[o].dat);
    		t[o].sum=t[o].lmax=t[o].rmax=t[o].dat;
    		return ;
    	}
    	int m=t[o].l+t[o].r>>1;
    	build(l,m,lson);
    	build(m+1,r,rson);
    	pushup(o);
    }
    
    inline void change(int o,int x,int v){
    	if(t[o].l==t[o].r){
    		t[o].sum=t[o].lmax=t[o].rmax=t[o].dat=v;
    		return ;
    	}
    	int m=t[o].l+t[o].r>>1;
    	if(x<=m)change(lson,x,v);
    	else change(rson,x,v);
    	pushup(o);
    }
    
    tree query(int o,int l,int r){
        if(t[o].l==l && t[o].r==r){
            return t[o];
        }
    	int m=t[o].l+t[o].r>>1;
        
        if(r<=m)return query(lson,l,r);
        else if(m<l)return query(rson,l,r);
        else{
        	tree ls=query(lson,l,m);
        	tree rs=query(rson,m+1,r);
            tree ans;
            ans.dat=max_3(ls.dat,rs.dat,ls.rmax+rs.lmax);
            ans.lmax=max_3(ls.sum,ls.lmax,ls.sum+rs.lmax);
            ans.rmax=max_3(rs.sum,rs.rmax,rs.sum+ls.rmax);
            ans.sum=ls.sum+rs.sum;
            return ans;
        }
    }
    
    #undef int
    int main(){
    #define int long long
    	freopen("CH4301.txt","r",stdin);
        int n,m;rd(n),rd(m);
        build(1,n,1);
        while(m--){
        	int op,x,y,v;
    		rd(op);
            if(op==1){
            	rd(x),rd(y);
                if(x>y)swap(x,y);
                tree ans=query(1,x,y);
                printf("%lld
    ",ans.dat);
            }
            else{
                rd(x),rd(v);
                change(1,x,v);
            }
        }
    	return 0;
    }
    /*
    题目描述
    给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
    1、“1 x y”,查询区间 [x,y] 中的最大连续子段和
    2、“2 x y”,把 A[x] 改成 y。
    对于每个查询指令,输出一个整数表示答案。
    第一行两个整数N,M。
    第二行N个整数A[i]。
    接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。
    对于每个查询指令输出一个整数表示答案。
    N≤500000,M≤100000
    N≤500000,M≤100000
    5 3
    1 2 -3 4 5
    1 2 3
    2 2 -1
    1 3 2
    输出样例:
    2
    -1
    sol:
    对于一个固定区间,求最大子段和我们有O(n)
    的算法。但是如何维护不同区间的LIS
    就成了一个问题。我们选择线段树解决区间问题,但使用线段树的话,我们需要明白,维护什么值,以
    及如何进行区间操作。
    
    那么我们思考,对于相邻的两个区间,他们的LIS
    有几种可能?
    1.左侧区间的LIS
    2.右侧区间的LIS
    3.两个区间合并后,中间新连接的部分
    
    前两点都好理解,针对第三点我们继续思考,中间部分能够成为LIS,其实就是我们从连接部分分别向前向后,获
    得一个尽可能大的前/后缀和。那么我们维护或者合并区间的LIS
    就需要维护三个值,区间最大子段和,最大前缀和,最大后缀和。而我们在合并区间的时候,如何维护前/后缀和呢?
    我们需要多维护一个区间和。
    
    整理我们得到,定义区间ls,rs
    合并得到区间d,每个区间维护区间和sum
    ,区间最大字段和maxs
    ,区间最大前缀和maxl
    ,区间最大后缀和maxr
    。则合并区间时,可得关系如下
    d.sum=ls.sum+rs.sum
    d.maxs=max(ls.maxs,rs.maxs,ls.maxr+rs.maxl)
    d.maxl=max(ls.maxl,ls.sum+rs.maxl)
    d.maxr=max(rs.maxr,rs.sum+ls.maxr)
    用线段树维护即可
    */
    

    区间查询最大值,单点修改

    /*
    reference:
    	
    translation:
    	
    solution:
    
    trigger:
    	
    note:
    	*
    record:
    
    date:
    	2019.09.01
    */
    #define N 200010
    #define lson o<<1
    #define rson o<<1|1
    
    struct tree{
    	int l,r;
    	int maxx;
    }t[N<<2]; 
    
    int n,m;
    int a[N];
    
    inline void pushup(int o){
    	t[o].maxx=max(t[lson].maxx,t[rson].maxx);
    }
    
    inline void change(int o,int x,int v){
    	if(t[o].l==t[o].r){
    		if(t[o].maxx<v)
    			t[o].maxx=v;
    		return ;
    	}
    	int mid=t[o].l+t[o].r>>1;
    	if(x<=mid)change(lson,x,v);//在左子树 
    	else change(rson,x,v);//在右子树
    	pushup(o);
    }
    
    inline void build(int l,int r,int o){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].maxx=a[l];
    		return;
    	}
    	int mid=l+r>>1;
    	build(l,mid,lson);
    	build(mid+1,r,rson);
    	pushup(o);
    }
    
    inline int query(int o,int x,int y){
    	if(x<=t[o].l && t[o].r<=y){
    		return t[o].maxx;
    	}
    	int val=-(1<<30);
    	int mid=t[o].l+t[o].r>>1;
    	if(x<=mid)val=max(val,query(lson,x,y));
    	if(mid<y)val=max(val,query(rson,x,y));
    	return val;
    }
    
    
    int main(){
    	#ifdef WIN32
    	freopen("","r",stdin);
    	#endif
    	rd(n),rd(m);
    	rep(i,1,n)rd(a[i]);
    	build(1,n,1);
    	while(m--){
    		char op[3];int x,y,v;
    		cin>>op;
    		if(op[0]=='Q'){
    			rd(x),rd(y);
    			printf("%d
    ",query(1,x,y));
    		}
    		else if(op[0]=='U'){
    			rd(x),rd(v);
    			change(1,x,v);
    		}
    	}
    	return 0;
    }
    

    区间最大公约数

    reference:https://www.acwing.com/solution/acwing/content/1047/

    #define N 500010
    #define lson o<<1
    #define rson o<<1|1
    struct tree{
        int l,r,dat;
    }t[N<<2];
    
    int a[N],cf[N],tr[N];
    int n,m;
    
    inline void pushup(int o){
    	t[o].dat=__gcd(t[lson].dat,t[rson].dat);
    }
    
    inline void build(int l,int r,int o){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].dat=cf[l];
    		return ;
    	}
    	int mid=l+r>>1;
    	build(l,mid,lson);
    	build(mid+1,r,rson);
    	pushup(o);
    }
    
    inline void update(int o,int x,int v){
    	if(x>n)return ;/////////////////////////////////
    	if(t[o].l==t[o].r){
    		t[o].dat+=v;
    		return ;
    	}
    	int mid=(t[o].l+t[o].r)>>1;
    	if(x<=mid)update(lson,x,v);
    	else update(rson,x,v);
    	pushup(o);
    }
    
    inline int ask(int o,int x,int y){
    	if(x>y)return 0;///////////////////////////////////////
    	if(x<=t[o].l && t[o].r<=y){
    		return abs(t[o].dat);
    	}
    	int mid=t[o].l+t[o].r>>1;
    	int gcd_l=0,gcd_r=0;
    	if(x<=mid)gcd_l=ask(lson,x,y);
    	if(mid<y)gcd_r=ask(rson,x,y);
    	return abs(__gcd(gcd_l,gcd_r));
    }
    
    inline void add(int x, int k){
    	for(int i=x;i<=n;i+=(-i)&i)
      		tr[i]+=k;
    }
    
    inline int query(int x){
    	int ans=0;
    	for(int i=x;i;i-=(-i)&i)
    		ans+=tr[i];
    	return ans; 
    }
    
    #undef int
    int main(){
    #define int long long
    	rd(n),rd(m);
    	rep(i,1,n){
    		rd(a[i]);
    		cf[i]=a[i]-a[i-1];
    	}
        build(1,n,1);
        while(m--){
    		int x,y,k;
            char op[5];scanf("%s",&op);
            if(op[0]=='Q'){
            	rd(x),rd(y);
            	printf("%lld
    ",__gcd(a[x]+query(x),ask(1,x+1,y)));
    		}
            else{
            	rd(x),rd(y),rd(k);
                update(1,x,k);
                update(1,y+1,-k);
                add(x,k);
                add(y+1,-k);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Mac安装Git以及Git和Github使用教程
    JMeter 聚合报告之 90% Line 参数说明
    [loj3525]喷泉公园
    dapr微服务
    Online SQL interpreter
    C# Math.Round()的银行家算法
    使用Visual Studio分析dump
    Qt高级——QTestLib单元测试框架
    深度学习:Keras入门(一)之基础篇
    前端使用a标签启动本地.exe程序
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634774.html
Copyright © 2020-2023  润新知