CF722C Destroying Array
题目大意:
给定由 \(n\) 个非负整数组成的数列 \(\lbrace a_i\rbrace\) 每次可以删除一个数,求每次删除操作后的最大连续子序列。
solution:
不难想到,我们可以使用一种支持修改和查询的数据结构。每次删除等价于把下标为 \(i\) 的数修改成一个极小值,此时的最大连续子序列就不会选择这个数。维护最大连续子序列的实现可以参考这道题:
接下来是细节的处理:
- 题目中 \(0<=a<=10^9\) 且 \(1<=n<=10^5\) 最大连续子序列的和会超过 \(\text {int}\) 我们需要开个 \(\text{long long }\)。
- 删除的数要修改成一个极小值 \(-9\times 10^{13}\) ,但是这样写会有一个问题,相信聪明的你一定能解决 (
其实也是对思路理解的反馈)。 - 对于查询,我们只输出根节点的信息就可以了。
看到这的同学,可以自己去写代码了(tf口吻)
代码
#include<cstdio>
#define ls u<<1
#define rs u<<1|1
using namespace std;
typedef long long LL;
const int N=1e5+5;
const LL INF=-90000000000000LL;
int a[N];
struct shu{
int l,r;
LL lmax,rmax,sum,smax;
}tr[N<<2];
inline LL maxx(LL x,LL y){return x>=y?x:y;}
inline void pushup(int u){
tr[u].sum=tr[ls].sum+tr[rs].sum;
tr[u].lmax=maxx(tr[ls].lmax,tr[ls].sum+tr[rs].lmax);
tr[u].rmax=maxx(tr[rs].rmax,tr[rs].sum+tr[ls].rmax);
tr[u].smax=maxx(maxx(tr[ls].smax,tr[rs].smax),tr[ls].rmax+tr[rs].lmax);
}
inline void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
if(l==r){
tr[u].lmax=a[l],tr[u].rmax=a[l],
tr[u].sum=a[l], tr[u].smax=a[l];
return ;
}
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
pushup(u);
}
inline void gai(int u,int x,LL y){
int l=tr[u].l,r=tr[u].r;
if(l==x&&x==r){
tr[u].lmax=y,tr[u].rmax=y,
tr[u].smax=y, tr[u].sum=y;
return ;
}
int mid=l+r>>1;
if(x<=mid) gai(ls,x,y);
else gai(rs,x,y);
pushup(u);
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
gai(1,x,INF);
LL ans=tr[1].smax;
printf("%lld\n",maxx(ans,0));
}
return 0;
}