题意:中文题
思路:倒着来,变成每次增加一个数,求增加前的最大连续和,用并查集,每次增加一个数之后,合并这个数左右的2个点,并且把旁边2个点的权值加上,记住如果旁边2个点的权值为0的话说明这个点没有数字,也就是不联通的,这个情况要把2个点从并查集里删除,才不会影响后面的计算
AC代码:
#include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "map" #include "algorithm" #include "stdio.h" #include "math.h" #define ll long long #define bug(x) cout<<x<<" "<<"UUUUU"<<endl; #define mem(a) memset(a,0,sizeof(a)) #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) using namespace std; const long long INF = 1e18+1LL; const int inf = 1e9+1e8; const int N=1e5+100; const ll mod=1e9+7; ll n,a[N],b[N],pre[N],M[N],ans[N]; void init(int n){ for(int i=0; i<=n+1; ++i) pre[i]=i; } int finds(int x){ return pre[x]=pre[x]==x?x:finds(pre[x]); } void unions(int x, int y){ int fx=finds(x), fy=finds(y); if(fx!=fy){ pre[fy]=fx; M[fx]+=M[fy]; M[fy]=0; } } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n; init(n); for(int i=1; i<=n; ++i){ cin>>a[i]; } for(int i=1; i<=n; ++i){ cin>>b[i]; } ll ma=0; for(int i=n; i>=1; --i){ ans[i]=ma; int flag1=0,flag2=0; if(!M[finds(b[i]-1)]) flag1=1; //bug(finds(b[i]+1)) bug(finds(b[i]-1)); if(!M[finds(b[i]+1)]) flag2=1; unions(b[i],b[i]-1); unions(b[i],b[i]+1); M[finds(b[i])]+=a[b[i]]; //cout<<M[finds(b[i])]<<" "; ma=max(ma,M[finds(b[i])]); if(flag1) pre[b[i]-1]=b[i]-1; if(flag2) pre[b[i]+1]=b[i]+1; } for(int i=1; i<=n; ++i) cout<<ans[i]<<" "; return 0; }