两题比较类似,就是连通块,另外,并查集两种初始化方式
destroying array,还有一种思路是把所有连通块的和加到集合里面,对于一个新元素,如果和已有连通块相邻,取出该连通块的值
加入新值,else 直接加
#include <iostream>
#include <string>
#include <cstring>
#include <string.h>
#include <sstream>
#include <stdio.h>
#include <set>
#include <sstream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <queue>
#include <stack>
#include <time.h>
#include <math.h>
#include <map>
using namespace std;
#define ctime printf("Time used = %.2f\n", (double)clock() / CLOCKS_PER_SEC);
#define fast ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define _for(i,a,b) for(int i = a;i < b;i++)
#define _rep(i,a,b) for(int i = a;i <= b;i++)
#define all(s) s.begin(), s.end()
#define local freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#define ll long long
#define fi first
#define se second
const int INF = 1e9;
const int maxn = 1e5 + 100;
int n, a[maxn], b[maxn], par[maxn], dx[] = { 1,-1 };
ll ma[maxn], ans[maxn];
bool vis[maxn] = { false };
int find(int x) {
if (par[x] == -1) return -1;
if (par[x] == x)
return x;
else return par[x] = find(par[x]);
}
int main() {
//local
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
//par[i] = i;
ma[i] = a[i];
}
for (int i = 1; i <= n; i++)
scanf("%d", b + i);
ll all = 0,sum;
memset(par, -1, sizeof(par));
for (int i = n; i > 1; i--) {
//vis[b[i]] = true;
par[b[i]] = b[i];
for (int j = 0; j < 2; j++) {
int nx = b[i] + dx[j];
if (0 < nx && nx <= n ) {
int p = find(nx);
if (p == -1) continue;
int pre = find(b[i]);
if (p != pre) {
par[pre] = p;
ma[p] += ma[pre];
}
}
}
all = max(all, ma[find(b[i])]);
ans[i] = all;
}
for (int i = 2; i <= n; i++)
cout << ans[i] << endl;
cout << 0 << endl;
}
就这样吧,自己慢慢调就ok了