Codeforces 722C(并查集 + 思维)

本文链接:http://www.cnblogs.com/Ash-ly/p/5932712.html

题目链接: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 }

 

posted @ 2016-10-05 19:46  vrsashly  阅读(958)  评论(0编辑  收藏  举报