C. Destroying Array 并查集,逆向思维
2024-08-21 14:38:22
用并查集维护线段,从后往前枚举没个删除的位置id[i]
那么,现在删除了这个,就是没有了的,但是上一个id[i + 1]就是还没删除的。
然后现在进行合并
int left = id[i + 1];(相当于每次都加入一个元素a[left])
它在这个位置,如果能和左右的合并,就是左右邻居都有元素,那么当然是合并最好,因为元素都是大于0的,越长越好。
合并的时候再记录一个数组sum[pos]表示以这个为根的总和是多少。
按并查集的思路更新整个并查集即可、
注意一点的就是,
要求ans[i]
那么ans[i + 1]是在没有id[i + 1]这个元素的前提下的最大值,现在有了这个元素,但是不见得会变大。
所以
ans[i] = max(ans[i + 1], sum[find(id[i + 1)]);
要和前一个比较一下
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
int fa[maxn];
LL sum[maxn];
int find(int u) {
if (fa[u] == u) return fa[u];
else return fa[u] = find(fa[u]);
}
void merge(int x, int y) {
x = find(x);
y = find(y);
if (x != y) {
fa[y] = x;
sum[x] += sum[y];
}
}
int a[maxn];
int id[maxn];
bool has[maxn];
LL ans[maxn];
void work() {
int n;
scanf("%d", &n);
for (int i = ; i <= n; ++i) fa[i] = i;
for (int i = ; i <= n; ++i) scanf("%d", &a[i]);
for (int i = ; i <= n; ++i) scanf("%d", &id[i]);
ans[n] = ;
for (int i = n - ; i >= ; --i) {
int left = id[i + ];
sum[left] = a[left];
if (has[left + ]) {
merge(left, left + );
}
if (has[left - ]) {
merge(left, left - );
}
ans[i] = max(ans[i + ], sum[find(left)]);
has[left] = ;
}
for (int i = ; i <= n; ++i) {
printf("%I64d\n", ans[i]);
}
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
work();
return ;
}
最新文章
- SQL Server 中怎么查看一个字母的ascii编码或者Unicode编码
- GO语言练习:组合的用法
- Office Word 2013发布带数学公式的博客
- settimeout 传递带有参数的函数
- ZOJ 1015 Fishing Net(判断弦图)
- Lucene 4.x实践1
- sql循环遍历
- [WPF疑难]如何禁用WPF窗口的系统菜单(SystemMenu)
- 【Python3之多线程】
- AJAX跨域问题解决方法(3)——被调用方解决跨域
- 最新鲜最详细的Android SDK下载安装及配置教程
- jmeter+ant+jekins的持续集成自动化搭建-基于虚拟机的linux系统
- Kali学习笔记13:操作系统识别
- google的android工具常用下载路径
- Python之路-python基础一
- 饿了么移动APP的架构演进
- AndroidManifest 配置主活动
- 当activity改变时,我们如何处理它
- go learning
- TopJUI | easyui HTML Dialog页面间GET方式数据传递