题目链接:http://codeforces.com/problemset/problem/722/C
思路:
题目给的操作数从第 1 个到第 N 个数是删除原数组中的一个数, 那么反过来从后往前就是增加原数组中的一个数, 每增加一个值, 那么就有四种情况: 第一种和前后都不连续, 即自成一个集合; 第二种:和前面的数连续, 即和前一个数在一个集合; 第三种和之后一个数连续, 即和之后的一个数在一个集合; 第四种既和前面一个数连续也和后面一个数连续,那么说明前后两个集合被这个数合并成一个集合. 然后合并的时候维护每个集合的元素和 sum, 利用 max 记录当前集合 sum 和新增集合的 sum 中的最大值.
代码:
1 #include <bits/stdc++.h> 2 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]; //合并两个集合的同时维护新集合的 sum 13 } 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 }
时间: 2024-10-12 12:18:30