SPOJ GGS1 線段樹

題意:求區間最大的子段和 這題之前寫過 然後今天重寫了一遍 感覺確實是區間合併的好題

解法:要開四個域 分別是當前段的和 左起連續最大和 右起連續最大和 區間最大子段和

然後詢問的時候維護一個當前最大和一個最大前綴和 總之就是要考慮到各種可能出現最大和的情況就可以了

#include<cstdio>
#include<iostream>
#include<limits.h>
using namespace std;
#define maxn 55555
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
int n,m,le[maxn<<2],ri[maxn<<2],sum[maxn<<2],ma[maxn<<2],x,y,mi,pre;
inline void up(int rt){
    sum[rt]=sum[ls]+sum[rs];
    le[rt]=max(le[ls],sum[ls]+le[rs]);
    ri[rt]=max(ri[rs],sum[rs]+ri[ls]);
    ma[rt]=max(max(ma[ls],ma[rs]),(ri[ls]+le[rs]));
}
inline void build(int rt,int l,int r){
    if(l==r){
        scanf("%d",&x);le[rt]=ri[rt]=sum[rt]=ma[rt]=x;return ;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    up(rt);
}
inline void query(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){
        mi=max(max(pre+le[rt],ma[rt]),mi);
        pre=max(pre+sum[rt],ri[rt]);
        return ;
    }
    if(L<=mid)query(ls,l,mid,L,R);
    if(mid<R)query(rs,mid+1,r,L,R);
}
int main(){
    scanf("%d",&n);build(1,1,n);
    scanf("%d",&m);
    while(m--){
        mi=-INT_MAX;pre=0;
        scanf("%d%d",&x,&y);query(1,1,n,x,y);
        printf("%d\n",mi);
    }
    return 0;
}

今天特意寫ggs6的時候重新改了一發這一題 這也是醉了 居然splay過不了

難道是常數真的太大了嗎

不對 應該是spoj真的是太慢了 反正改了結構體就過了 這真的是醉了啊

以下是tle的代碼 感覺看還是能看的 就是真的卡死了啊

#include<map>
#include<set>
#include<cstring>
#include<stdio.h>
#include<vector>
#include<cstdio>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<limits.h>
using namespace std;
#define maxn 222222
#define inf 2100000000
#define ls ch[rt][0]
#define rs ch[rt][1]
#define rrs ch[root][1]
#define rls ch[root][0]
int ch[maxn][2],key[maxn],fa[maxn],sz[maxn];
int lmax[maxn],rmax[maxn],sum[maxn],smax[maxn];
int root,cnt,lim;
inline bool scan(int &ret) {
    char c; int sgn;
    if(c=getchar(),c==EOF) return 0; //EOF
    while(c!='-'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    ret*=sgn;
    return 1;
}
inline void init(int rt){
    smax[rt]=lmax[rt]=rmax[rt]=-inf;
    key[rt]=sum[rt]=0;
    ch[rt][0]=ch[rt][1]=fa[rt]=sz[rt]=0;
}
inline void up(int rt){
    if(!rt)return ;
    lmax[rt]=lmax[ls];
    lmax[rt]=max(lmax[rt],sum[ls]+key[rt]+lmax[rs]);
    lmax[rt]=max(lmax[rt],sum[ls]+key[rt]);
    rmax[rt]=rmax[rs];
    
	rmax[rt]=max(rmax[rt],sum[rs]+key[rt]+rmax[ls]);
    rmax[rt]=max(rmax[rt],sum[rs]+key[rt]);
    sum[rt]=sum[ls]+sum[rs]+key[rt];
    
    smax[rt]=max(smax[ls],smax[rs]);
	int ll,rr;
	ll=max(0,rmax[ls]); rr=max(0,lmax[rs]);
    smax[rt]=max(smax[rt],ll+rr+key[rt]);
    sz[rt]=sz[ls]+sz[rs]+1;
}
inline void rot(int rt){
    int f=fa[rt],side=ch[f][1]==rt,ll=ch[rt][!side];
    fa[ll]=f,ch[f][side]=ll;
    fa[rt]=fa[f],ch[fa[f]][ch[fa[f]][1]==f]=rt;
    fa[f]=rt,ch[rt][!side]=f;
    up(f),up(rt);
}
inline void splay(int rt,int aim){
    while(fa[rt]!=aim){
        int f=fa[rt],ff=fa[f];
        if(ff==aim)rot(rt);
        else if((ch[f][1]==rt)==(ch[ff][1]==f))rot(f),rot(rt);
        else rot(rt),rot(rt);
    }
    if(!aim)root=rt;
}

int cur;
inline void find(int sub,int tot){
    int rt=sub;
    while(1){
        if(sz[ls]==tot-1)break;
        if(sz[ls]>=tot)rt=ls;
        else tot-=sz[ls]+1,rt=rs;
    }
    cur=rt;
    splay(rt,fa[sub]);
}
inline void insert(int a,int b)
{
    find(root,a+1);
	init(cnt+1);
    ch[++cnt][1]=ch[root][1];fa[rrs]=cnt;
    key[cnt]=b;ch[root][1]=cnt;
    fa[cnt]=root;ch[cnt][0]=0;
    up(cnt); up(root);
}
inline void delet(int a){
    find(root,a+1);find(rrs,1);
    ch[rrs][0]=rls;
    fa[rls]=rrs;
    root=rrs;fa[root]=0;ch[0][1]=root;
    up(root);
}
inline void  replace(int n,int val){
    find(root,n+1);key[cur]=val;
    up(cur); //up(root);
}
int qu(int a,int b){
    find(root,a);
    find(rrs,b-a+2);
    return smax[ch[rrs][0]];
}
char cmd[12];
int n,m,x,y;
int main(){
    while(~scanf("%d",&n)){
        root=0;init(0);lim=inf;
        for(int i=1;i<=n;++i){
            init(i);scan(key[i]);fa[i]=i-1;ch[i-1][1]=i;sz[i]=1;
            up(i-1);sum[i]=lmax[i]=rmax[i]=smax[i]=key[i];
            splay(i,0);
        }
        splay(1,0);
        init(n+1);
        fa[n+1]=1,ch[1][0]=n+1;sz[n+1]=1;up(n+1);
        splay(n+1,0);splay(n,0);init(n+2);
        fa[n+2]=n;ch[n][1]=n+2;sz[n+2]=1;up(n);
        splay(n+2,0);cnt=n+2;
        scan(m);
        while(m--){
            scanf("%d%d",&x,&y);
            printf("%d\n",qu(x,y));
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章