本文链接:
题目链接:
思路:
题目给的操作数从第 1 个到第 N 个数是删除原数组中的一个数, 那么反过来从后往前就是增加原数组中的一个数, 每增加一个值, 那么就有四种情况: 第一种和前后都不连续, 即自成一个集合; 第二种:和前面的数连续, 即和前一个数在一个集合; 第三种和之后一个数连续, 即和之后的一个数在一个集合; 第四种既和前面一个数连续也和后面一个数连续,那么说明前后两个集合被这个数合并成一个集合. 然后合并的时候维护每个集合的元素和 sum, 利用 max 记录当前集合 sum 和新增集合的 sum 中的最大值.
代码:
1 #include2 3 typedef long long LL; 4 const int MAXN = 100000; 5 using namespace std; 6 LL pre[MAXN + 3], cnt[MAXN + 3], a[MAXN + 3], pos[MAXN + 3], visit[MAXN + 3], ans[MAXN + 3]; 7 8 int Find(int x) { return x == pre[x] ? x : pre[x] = Find(pre[x]); } 9 10 void mix(int x, int y) {11 int fx = Find(x), fy = Find(y);12 if(fx != fy) pre[fy] = fx, cnt[fx] += cnt[fy]; //合并两个集合的同时维护新集合的 sum13 }14 15 int main() {16 ios_base::sync_with_stdio(0); cin.tie();17 int n; cin >> n;18 for(int i = 1; i <= n; i++) {19 cin >> a[i];20 pre[i] = i, visit[i] = 0;21 }22 for(int i = 0; i < n; i++) cin >> pos[i];23 LL maxn = 0;24 for(int i = n - 1; i >= 0; i--) {25 int tp = pos[i];26 cnt[tp] = a[tp], visit[tp] = 1, ans[i] = maxn;27 if(tp != 1 && visit[tp - 1]) mix(tp, tp - 1); // 新增一个元素后形成的四种情况28 if(tp != n && visit[tp + 1]) mix(tp, tp + 1);29 maxn = max(maxn, cnt[ Find(tp) ]);30 }31 for(int i = 0; i < n; i++) cout << ans[i] << endl;32 return 0;33 }