CodeForces 722C Destroying Array(并查集和我奇怪的二叉树)
来源:互联网 发布:sql的4种基本操作语句 编辑:程序博客网 时间:2024/06/08 02:43
【题意】
给你一个序列A, 然后一个序列B,按序列B的顺序依次删除第B[i]个数,问你当前最大连续字段和是多少,这段和不能包括被删除的数。
例如
4
1 3 2 5
3 4 1 2
删除第B[1] = 3个数事,最大字段和是第四个数5,然后依次是4 3 0.
【分析】
先来说说不靠谱的二叉树吧,在第32个点超时了。
我的思路是,每次删除一个数,必然会把一个区间分成两个区间,这样就可以看成这个节点分成两个节点,节点的信息维护区间左端点右端点,和区间最大字段和。每次删除一个数,就会衍生出两个节点,每个节点的最大字段和就两个子节点的最大字段和的最大值。理想情况下是nlogn的复杂度,但是退化成链的情况下复杂度就是n^2了。
代码
#include<cstdio>#include<algorithm>using namespace std;struct node{ long long l, r, maxi; long long lson, rson;} a[1000001];long long c[1000001];long long f[1000001];long long tot = 1;long long NewNode(long long root, int l, int r){ a[root].l = l; a[root].r = r; a[root].maxi = f[r] - f[l - 1]; a[root].lson = a[root].rson = 0; return root;}void updata(long long root){ a[root].maxi = max(a[a[root].lson].maxi, a[a[root].rson].maxi);}void dfs(long long root, long long k){ //printf("%d %d %d %d\n", root, a[root].l, a[root].r, a[root].maxi); //getchar(); if(a[root].l == a[root].r) { a[root].maxi = 0; }else if(a[root].lson == 0 && a[root].rson == 0){ a[root].lson = NewNode(++tot, a[root].l, k - 1); a[root].rson = NewNode(++tot, k + 1, a[root].r); }else{ if(a[root].lson && k <= a[a[root].lson].r){ dfs(a[root].lson, k); } else if(a[root].rson && k >= a[a[root].rson].l){ dfs(a[root].rson, k); } } updata(root);}int main(){ long long n; scanf("%lld", &n); for(int i = 1; i <= n; i++){ scanf("%lld", &c[i]); f[i] = f[i - 1] + c[i]; } NewNode(1, 1, n); for(int i = 1; i <= n; i++){ long long k; scanf("%lld", &k); dfs(1, k); printf("%lld\n", a[1].maxi); } return 0;}
正解是并查集。倒着思考,删除一个数就加上一个数,没加入一个数就判断一下能不能吧它左右两边连起来。就是并查集了。
代码(记得要用long long)
#include<cstdio>#include<algorithm>using namespace std;long long f[200001];long long a[200011];long long c[200001];long long s[200001];long long flag[200001];long long ans[200001];long long n, maxi = 0;long long find(long long k){ if(f[k] == k) return k; else f[k] = find(f[k]); return f[k];}int main(){ scanf("%lld", &n); for(int i = 1; i <= n; i++){ f[i] = i; scanf("%lld", &a[i]); } for(int i = 1; i <= n; i++){ scanf("%lld", &c[i]); } for(int i = n; i > 0; i--){ ans[i] = maxi; flag[c[i]] = 1; s[c[i]] = s[find(c[i] - 1)] + s[find(c[i] + 1)] + a[c[i]]; maxi = max(maxi, s[c[i]]); if(flag[c[i] - 1]) f[find(c[i] - 1)] = c[i]; if(flag[c[i] + 1]) f[find(c[i] + 1)] = c[i]; } for(int i = 1; i <= n; i++) { printf("%lld\n", ans[i]); } return 0;}
0 0
- CodeForces 722C Destroying Array(并查集和我奇怪的二叉树)
- codeforces 722C. Destroying Array(并查集||set)
- codeforces 722C Destroying Array ( 并查集 / Multiset )
- 【Codeforces 722 C Destroying Array】+ 并查集
- Codeforces 722C Destroying Array(并查集)
- 并查集巧妙用法(codeforces)C. Destroying Array
- Codeforces 722C Destroying Array【逆序(离线)思维+并查集】
- CodeForces 722C. Destroying Array(并查集 好题)
- 并查集(Destroying Array,cf 722C)
- [codeforces]C. Destroying Array——并查集
- Codeforces Round 722C:Destroying Array(并查集,好题)
- codeforces 722C Destroying Array 并查集带权
- Codeforces722 C. Destroying Array (并查集)
- 【codeforces 722C】【逆向思维 离线+并查集】C. Destroying Array 【给你n个数,每次摧毁一个,求每摧毁一个的最大连续和(被摧毁的点的两边不连续)】
- Destroying Array(并查集)
- Codeforces722C-Destroying Array(线段树 or 并查集)
- CodeForces - 722C Destroying Array (set)
- codeforces 722C Destroying Array
- SVM算法下如何使用SMO算法优化拉格朗日乘子
- 广域网配置实例 及 路由详细过程
- 谈谈软件测试领域
- linux下如何使用sftp命令
- node.js学习笔记之写文件
- CodeForces 722C Destroying Array(并查集和我奇怪的二叉树)
- Linux Root密码修改
- Unix高级环境编程之获取用户口令信息getpwuid函数
- Error opening terminal: xterm 解决办法
- 【JZOJ4924】【NOIP2017提高组模拟12.17】向再见说再见
- Gradle编译出现OOM错误
- Mongodb简单安装
- 基于avr的pwm自动调光实现
- 【Spring】XML配置整合Mybatis