题意
https://vjudge.net/problem/CodeForces-722C
给你一个由n个非负整数组成的数列 a1 ,a2 ,...,an 。
你将要一个一个摧毁这个数列中的数。并且,现在给你一个由 1 到 n 组成的序列来告诉你每个数被摧毁的时间顺序。
每当一个元素被摧毁时,你需要找到这个当前数列中的未被摧毁的数组成的和最大的连续子序列,另外,如果当前剩余的序列是空的的话,最大和就是0。
思路
正着删无法操作,那么我们考虑倒着加!每次加入一个点,判断这个点左右是否有数,有的话就合并到这个点来。注意要先将sum合并,再将父亲合并。
代码
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) ll a[N],b[N],n,pre[N],sum[N]; ll find(ll x) { if(x==pre[x]) return x; return pre[x]=find(pre[x]); } int main() { std::ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=n;i++) cin>>b[i]; stack<ll> st; st.push(0); ll mx=0; for(int i=n;i>1;i--) { int x=b[i]; ll fx=find(b[i]); if(!fx) { fx=x; pre[x]=x; sum[x]=a[x]; // cout<<"s:"<<x<<" "<<sum[x]<<" "<<find(x+1)<<endl; } if(x>1&&find(x-1)&&find(x-1)!=find(x)) { sum[fx]+=sum[find(x-1)]; pre[find(x-1)]=pre[fx]; } if(x<n&&find(x+1)&&find(x+1)!=find(x)) { sum[fx]+=sum[find(x+1)]; pre[find(x+1)]=pre[fx]; // cout<<"hh:"<<sum[fx]<<" "<<sum[find(x+1)]<<endl; } mx=max(mx,sum[fx]); // cout<<sum[x]<<endl; st.push(mx); } while(!st.empty()) { cout<<st.top()<<endl; st.pop(); } return 0; }