描述:
给你n个数,每次摧毁一个,求每摧毁一个的最大连续和(被摧毁的点的两边不连续)。
思路:
并查集,离线操作。
将操作倒着进行,一开始所有数字都没有加入到数组中,然后倒着一个一个加入,更新最大值。
#include <bits/stdc++.h>
#define pr(x) cout << #x << "= " << x << " " ;
#define pl(x) cout << #x << "= " << x << endl;
#define ll __int64
using namespace std;
const int N=1e5+10;
int p[N],b[N],vis[N],n;
ll a[N],sum[N],ans[N];
int Find(int x){
return p[x]==x?x:p[x]=Find(p[x]);
}
void unite(int a, int b){
if(b>n || b<0)return;
if(vis[b]==0)return;
a=Find(a);b=Find(b);
if(a!=b){
p[b]=a;
sum[a]=sum[a]+sum[b];
sum[b]=0;
}
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
cin>>n;
for(int i=1; i<=n; i++)p[i]=i;
for(int i=1; i<=n; i++)cin>>a[i];
for(int i=1; i<=n; i++)cin>>b[i];
for(int i=1; i<=n; i++)sum[i]=a[i];
ll mx=0;
for(int i=n; i>=1; i--){
ans[i]=mx;vis[b[i]]=1;
unite(b[i], b[i]-1);//向前合并
unite(b[i], b[i]+1);//向后合并
mx=max(mx, sum[b[i]]);
}
for(int i=1; i<=n; i++)cout<<ans[i]<<endl;
return 0;
}