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
原创粉丝点击