zoukankan      html  css  js  c++  java
  • 超神线段树 山海经

      

    问题 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(){;}

  • 相关阅读:
    jquery实现密码框显示提示文字
    Jquery显示和隐藏的4种简单方法
    JavaScript创建对象的写法
    jQuery实现用户注册的表单验证
    Jquery操作Cookie取值错误的解决方法
    java泛型笔记一
    数字电路与系统-组合逻辑电路的竞争冒险现象1
    数字电路与系统-组合逻辑电路分析和设计
    数字电路与系统-逻辑函数的化简
    数字电路与系统-逻辑函数及其描述方法
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632738.html
Copyright © 2011-2022 走看看