题意:求区间最大的子段和 这题之前写过 然后今天重写了一遍 感觉确实是区间合并的好题
解法:要开四个域 分别是当前段的和 左起连续最大和 右起连续最大和 区间最大子段和
然后询问的时候维护一个当前最大和一个最大前缀和 总之就是要考虑到各种可能出现最大和的情况就可以了
#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;
}