題解 CF722C 【Destroying Array】
阿新 • • 發佈:2021-07-29
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; }