标签:坐标 else etc build problem ret live 二分 数列
题目:https://cn.vjudge.net/problem/UVALive-3938
将数列二分存储在线段树
并记录每段前缀最大值qian,后缀最大值hou,总合sum,最大中间和w
与各自坐标;
建记录如上的线段树(更新规则见代码)
后得到范围解题便可!
#include <cstdio> 
#include <cstring>  
#include <iostream>     
using namespace std;  
struct node{  
    long long  qian,hou,w,sum;  
    int l,r,p,s;  
}e[2000010];  
long long c[500005];
long long read()
{
long long x=0,f=1;char ch=getchar();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
void build(int a,int b,int o)  
{  
    if(a==b)  
    {  
        e[o].sum=e[o].w=e[o].qian=e[o].hou=c[a];  
        e[o].l=e[o].r=e[o].p=e[o].s=a;  
        return ;  
    }  
    int mid=(a+b)/2;  
    build(a,mid,2*o);  
    build(mid+1,b,2*o+1);  
    e[o].sum=e[2*o].sum+e[2*o+1].sum;  
    long long a1=e[2*o].w,a2=e[2*o+1].w,s1=e[2*o].hou+e[2*o+1].qian;  
    if(a1>=a2&&a1>=s1){e[o].w=a1;e[o].l=e[2*o].l;e[o].r=e[2*o].r;}  
    else if(s1>=a2){e[o].w=s1;e[o].l=e[2*o].s;e[o].r=e[2*o+1].p;}  
    else {e[o].w=a2;e[o].l=e[2*o+1].l;e[o].r=e[2*o+1].r;}  
    if(e[2*o].qian>=e[2*o].sum+e[2*o+1].qian)  
    {e[o].qian=e[2*o].qian;e[o].p=e[2*o].p;  }  
    else  
    { e[o].qian=e[2*o].sum+e[2*o+1].qian;e[o].p=e[2*o+1].p; }  
    if(e[2*o+1].hou>e[2*o].hou+e[2*o+1].sum)  
    { e[o].hou=e[2*o+1].hou;e[o].s=e[2*o+1].s;}  
    else  
    { e[o].hou=e[2*o+1].sum+e[2*o].hou;e[o].s=e[2*o].s;}  
}  
node jie(int c,int l,int r,int L,int R)  
{  
    if(L==l&&R==r)return e[c];  
    int mid=L+(R-L)/2;  
    if(r<=mid)return jie(2*c,l,r,L,mid);  
    else if(l>mid)return jie(2*c+1,l,r,mid+1,R);  
    else  
    {  
        node ri,le,da;  
        ri=jie(2*c,l,mid,L,mid);  
        le=jie(2*c+1,mid+1,r,mid+1,R);  
        da.sum=le.sum+ri.sum;  
        if(ri.w>=le.w&&ri.w>=ri.hou+le.qian){da.w=ri.w;da.l=ri.l;da.r=ri.r;}  
        else if(ri.hou+le.qian>=le.w){da.w=ri.hou+le.qian;da.l=ri.s;da.r=le.p;}  
        else {da.w=le.w;da.l=le.l;da.r=le.r;}  
        if(ri.qian>=ri.sum+le.qian)  
        {da.qian=ri.qian;da.p=ri.p;}  
        else  
        {da.qian=ri.sum+le.qian;da.p=le.p;}  
        if(le.hou>ri.hou+le.sum)  
        { da.hou=le.hou;da.s=le.s;}  
        else  
        {da.hou=le.sum+ri.hou;da.s=ri.s;}  
        return da;  
    }  
}  
int main()  
{  
    int n,m,t=0;;  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {    
        for(int i=1;i<=n;i++)  
            c[i]=read();
        build(1,n,1);  
        node ans;  
        t++;
        cout<<"Case "<<t<<":"<<endl;  
        for(int i=0;i<m;i++)  
        {  
            int l=read(),r=read();
            ans=jie(1,l,r,1,n);  
            cout<<ans.l<<" "<<ans.r<<endl;  
        }  
    }  
    return 0;  
}  
标签:坐标 else etc build problem ret live 二分 数列
原文地址:http://www.cnblogs.com/0degreeofsail/p/7146000.html