#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
inline namespace usual{
#define space ' '
#define endl '\n'
template<typename T>T max(T a,T b){return a>b?a:b;}
template<typename T>T min(T a,T b){return a<b?a:b;}
inline long long input(){
long long a=0,f=1;
char tmp=getchar();
while(!isdigit(tmp)){if(tmp=='-')f=-1;tmp=getchar();}
while(isdigit(tmp)){a=(a<<3)+(a<<1)+(tmp^48);tmp=getchar();}
return a*f;
}
class out{
private:
void output(long long x){
if(x<0)putchar('-'),x=-x;
if(x>9)output(x/10);
putchar(x%10+48);
}
void output(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)output(x/10);
putchar(x%10+48);
}
void output(char t){
putchar(t);
}
void output(const char *t){
while(*t)putchar(*(t++));
}
public:
template<class T>out operator<<(T x){
output(x);
return *this;
}
}opt;
}
#define int long long
template<int _size>class segment_tree{//要支持:区间改值,区间查找
private:
struct node{
int l,r,maxx,minx,flag=-1;
int size(){return r-l+1;}
}t[_size<<2|1];
public:
void update(int p){
t[p].maxx=max(t[p<<1].maxx,t[p<<1|1].maxx);
t[p].minx=min(t[p<<1].minx,t[p<<1|1].minx);
}
void spread(int p){
if(t[p].flag==-1)return;
t[p<<1].maxx=t[p<<1].minx=t[p<<1].flag=t[p].flag;
t[p<<1|1].maxx=t[p<<1|1].minx=t[p<<1|1].flag=t[p].flag;
t[p].flag=-1;
}
void build(int p,int l,int r,int a[]){
t[p].l=l,t[p].r=r;
if(l==r){t[p].minx=t[p].maxx=a[l];return;}
int mid=l+r>>1;
build(p<<1,l,mid,a);
build(p<<1|1,mid+1,r,a);
update(p);
}
void change(int p,int l,int r,int val){
if(l>r)return;
if(l<=t[p].l&&t[p].r<=r){
t[p].minx=t[p].maxx=val;
t[p].flag=val;
return;
}
spread(p);
if(l<=t[p<<1].r)change(p<<1,l,r,val);
if(r>=t[p<<1|1].l)change(p<<1|1,l,r,val);
update(p);
}
int querymax(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)return t[p].maxx;
spread(p);
int res=0;
if(l<=t[p<<1].r)res=max(res,querymax(p<<1,l,r));
if(r>=t[p<<1|1].l)res=max(res,querymax(p<<1|1,l,r));
return res;
}
int querymin(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)return t[p].minx;
spread(p);
int res=0x7fffffff;
if(l<=t[p<<1].r)res=min(res,querymin(p<<1,l,r));
if(r>=t[p<<1|1].l)res=min(res,querymin(p<<1|1,l,r));
return res;
}
};
segment_tree<100000>T;
/*
维护一个数列,初始时有n个元素
每次删除掉其中一个元素,然后问最大子段和
n≤100000
应该是水题
看某个元素所属子段
开个数组t[],t[i]表示点i的元素所属子段的编号
删元素:找到t[i],二分其左右端点,新建两个子段,然后把其左右子段给重新染色,线段树维护,
并且要标记原先的那个子段已经失效
再用个堆维护长度最大值即可
*/
struct segment{
int p,val;
bool operator<(segment x)const{
return this->val<x.val;
}
};
std::priority_queue<segment>Q;
int n,a[100001],t[100001],sum[100001],cnt;
bool flag[1000001];
void read(){
n=input();
for(int i=1;i<=n;i++)
a[i]=input();
}
void answer(){
for(int i=1;i<=n;i++){
int q=input();
flag[T.querymax(1,q,q)]=1;
int low=1,high=q,l,r;
while(low<=high){
int mid=low+high>>1;
if(T.querymax(1,mid,q)==T.querymin(1,mid,q))high=mid-1;
else low=mid+1;
}
l=low;
low=q,high=n;
while(low<=high){
int mid=low+high>>1;
if(T.querymax(1,q,mid)==T.querymin(1,q,mid))low=mid+1;
else high=mid-1;
}
r=high;
T.change(1,l,q-1,++cnt);
Q.push({cnt,sum[q-1]-sum[l-1]});
T.change(1,q+1,r,++cnt);
Q.push({cnt,sum[r]-sum[q]});
int ans=0;
while(Q.size()&&flag[Q.top().p])Q.pop();
if(Q.size()){ans=Q.top().val;}
opt<<ans<<endl;
}
}
void pre(){
cnt++;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i];
t[i]=cnt;
}
Q.push({cnt,sum[n]});
T.build(1,1,n,t);
}
#undef int
int main(){
read();
pre();
answer();
return 0;
}
理论复杂度O(nlog2n),但由于常数过于巨大实测当n=100000时不开优化开关要2.5s,开O2的话也要1.3s。。