• 超神线段树 山海经


      

    问题 K: 山海经

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    “南山之首日鹊山。其首日招摇之山,临于西海之上,多桂,多金玉。有草焉,其状如韭而青华,其名日祝余,食之不饥……又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金。

    又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上。……”

    《山海经》是以山为纲,以海为线记载古代的河流、植物、动物及矿产等情况,而且每一条记录路线都不会有重复的山出现。某天,你的地理老师想重游《山海经》中的路线,为了简化问题,老师已经把每座山用一个整数表示他对该山的喜恶程度,他想知道第a座山到第b座山的中间某段路(i,j)。能使他感到最满意,即(i,j)这条路上所有山的喜恶度之和是(c,d)(a≤c≤d≤b)最大值。于是老师便向你请教,你能帮助他吗?值得注意的是,在《山海经》中,第i座山只能到达第i+1座山。

    输入

    输入第1行是两个数,n,m,2≤n≤100000,1≤m≤100000,n表示一共有n座山,m表示老师想查询的数目。

    第2行是n个整数,代表n座山的喜恶度,绝对值均小于10000。

    以下m行每行有a,b两个数,1≤a≤j≤b≤m,表示第a座山到第b座山。

    输出

    一共有m行,每行有3个数i,j,s,表示从第i座山到第j座山总的喜恶度为s。显然,对于每个查询,有a≤i≤j≤b,如果有多组解,则输出i最小的,如果i也相等,则输出j最小的解。

    样例输入

    5 3
    5 -6 3 -1 4
    1 3
    1 5
    5 5

    样例输出

    1 1 5
    3 5 6
    5 5 4
         超级麻烦QAQ。。调了一个晚上
         区间连续和的最大,那么有三种可能,前缀最大,中间一段最大,后缀最大
         又因为要输出区间坐标,还要维护前缀坐标。。。。(前缀不需要左端点,后缀。。废话)以及节点总和。 
         那么pushup还有查询该怎么转移呢?
          x.l_max=max(lc.l_max,lc.sum+rc.l_max);
          x.mid_max=max(lc.mid_max,lc.r_max+rc.l_max,rc.mid_max);
          x.r_max=max(rc.r_max,rc.sum+lc.r_max);
          注意值相同按左右端点。 
          写进一个函数求一下就行了~~
         
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define ll long long
    #define N 100000
    #define hmid a.hr+b.hl
    using namespace std;
    int n,m,a[N+5];
    struct tree
    {
    	int l,r,hl,hm,hr,h,r1,l2,r2,l3;
    } t[N*4+5];
    ll read()
    {
    	ll sum=0,f=1;char x=getchar();
    	while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    	while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
    	return sum*f;
    }
    tree pushup(tree a,tree b)
    {
    	tree ans;
    	ans.l=a.l;ans.r=b.r;
    	ans.h=a.h+b.h;
    	if(a.hl>=a.h+b.hl)
    	   ans.hl=a.hl,ans.r1=a.r1;
    	else
    	    ans.hl=a.h+b.hl,ans.r1=b.r1;
    	if(a.hr+b.h<b.hr)
    	    ans.hr=b.hr,ans.l3=b.l3;
    	else
    	    ans.hr=a.hr+b.h,ans.l3=a.l3;
    	if(b.hm>hmid&&b.hm>a.hm)
    		ans.hm=b.hm,ans.l2=b.l2,ans.r2=b.r2;
    	else
    	{
    		if(hmid>a.hm)
    		    ans.hm=hmid,ans.l2=a.l3,ans.r2=b.r1;
    		else
    		{
    			if(a.hm>hmid)
    			   ans.hm=a.hm,ans.r2=a.r2,ans.l2=a.l2;
    			else
    			{
    				if(a.l2<=a.l3)
    				    ans.hm=a.hm,ans.l2=a.l2,ans.r2=a.r2;
    				else
    				    ans.hm=hmid,ans.l2=a.l3,ans.r2=b.r1;
    			}
    		}
    	}
    	return ans;
    }
    void build(int l,int r,int x)
    {
    	t[x].l=l;t[x].r=r;
    	if(l==r)
    	{
    		t[x].h=t[x].hl=t[x].hm=t[x].hr=a[l];
    		t[x].l2=t[x].l3=l;t[x].r1=t[x].r2=r;
    		return;
    	}
    	int mid=(l+r)/2;
    	build(l,mid,x*2);
    	build(mid+1,r,x*2+1);
    	t[x]=pushup(t[x*2],t[x*2+1]);
    }
    tree Q(int l,int r,int x)
    {
    	if(t[x].l>=l&&t[x].r<=r)
    	{
    		return t[x];
    	}
    	int mid=(t[x].l+t[x].r)/2;
    	if(r<=mid)
            return Q(l,r,x*2);
    	else
    	{
    		if(l>mid)
    		     return Q(l,r,x*2+1);
    		else
    			return pushup(Q(l,r,x*2),Q(l,r,x*2+1));
    	}
    }
    int yjn()
    {
    //	freopen("hill.in","r",stdin);
       // freopen("hill.out","w",stdout);
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    	    a[i]=read();
    	build(1,n,1);
    	int x,y;
    	while(m--)
    	{
    		scanf("%d%d",&x,&y);
    		tree ans=Q(x,y,1);
    		if(ans.hr>ans.hl&&ans.hr>ans.hm)
    		    printf("%d %d %d
    ",ans.l3,ans.r,ans.hr);
    		else
    		    if(ans.hl>ans.hm)
    		        printf("%d %d %d
    ",ans.l,ans.r1,ans.hl);
    		    else
    		        printf("%d %d %d
    ",ans.l2,ans.r2,ans.hm);
    	}
    }
    int qty=yjn();
    int main(){;}

  • 相关阅读:
    联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
    联想 Z5S(L78071)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.370
    联想 Z5(L78011) 免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.254
    联想 S5 Pro(L78041)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 5.0.123
    第二阶段 冲刺八
    第二阶段 冲刺七
    第二阶段 冲刺六
    第二阶段 冲刺五
    代码大全阅读笔记03
    学习进度十二
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632738.html
Copyright © 2020-2023  润新知