zoukankan      html  css  js  c++  java
  • 线段树 或者 并查集 Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C

    http://codeforces.com/contest/722/problem/C

    题目大意:给你一个串,每次删除串中的一个pos,问剩下的串中,连续的最大和是多少。

    思路一:正方向考虑问题,那么就线段树+分类讨论一下就好了,然后代码中flag表示能否转移

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 100000 + 5;
    struct Tree{
        bool lf, rf;
        bool flag;
        LL val, lval, rval;
    }tree[maxn << 2];
    int n;
    int b[maxn];
    
    inline void push_up(int o){
        int lb = o << 1, rb = o << 1 | 1;
        if (tree[lb].flag && tree[rb].flag){
            tree[o].lf = tree[o].rf = true;
            tree[o].lval = tree[o].rval = tree[o].val = tree[lb].val + tree[rb].val;
            return ;
        }
        tree[o].flag = false;
    
        if (tree[lb].lf == false) tree[o].lf = false, tree[o].lval = 0;
        else {
            tree[o].lf = true;
            if (tree[lb].flag && tree[rb].lf) tree[o].lval = tree[lb].lval + tree[rb].lval;
            else tree[o].lval = tree[lb].lval;
        }
    
        if (tree[rb].rf == false) tree[o].rf = false, tree[o].rval = 0;
        else {
            tree[o].rf = true;
            if (tree[rb].flag && tree[lb].rf) tree[o].rval = tree[rb].rval + tree[lb].rval;
            else tree[o].rval = tree[rb].rval;
        }
    
        tree[o].val = max(tree[lb].val, tree[rb].val);
        if (tree[lb].rf && tree[rb].lf){
            tree[o].val = max(tree[o].val, tree[lb].rval + tree[rb].lval);
        }
    
    }
    
    void build_tree(int l, int r, int o){
        if (l == r) {
            LL val;
            scanf("%lld", &val);
            tree[o].val = tree[o].lval = tree[o].rval = val;
            tree[o].flag = tree[o].lf = tree[o].rf = true;
            return ;
        }
        tree[o].lf = tree[o].rf = tree[o].flag = true;
        int mid = (l + r) / 2;
        if (l <= mid) build_tree(l, mid, o << 1);
        if (r > mid) build_tree(mid + 1, r, o << 1 | 1);
        push_up(o);
    }
    
    void update(int l, int r, int pos, int o){
        if (l == r && l == pos){
            tree[o].val = 0;
            tree[o].flag = tree[o].lf = tree[o].rf = false;
            return ;
        }
        int mid = (l + r) / 2;
        if (pos <= mid) update(l, mid, pos, o << 1);
        if (pos > mid) update(mid + 1, r, pos, o << 1 | 1);
        push_up(o);
    }
    
    int main(){
        scanf("%d", &n);
        build_tree(1, n, 1);
    
        for (int i = 1; i <= n; i++){
            int pos; scanf("%d", &pos);
            update(1, n, pos, 1);
            printf("%lld
    ", tree[1].val);
        }
        return 0;
    }
    View Code

    思路二:逆向考虑,使用并查集,因为最初是0,所以我们只需要逆向考虑就好了。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 1e5 + 5;
    LL a[maxn], b[maxn], sum[maxn], ans[maxn];
    bool vis[maxn];
    int n;
    int par[maxn];
    
    int pfind(int x){
        if (x == par[x]) return x;
        return par[x] = pfind(par[x]);
    }
    
    void unite(int x, int y){
        x = pfind(x), y = pfind(y);
        par[x] = y;
        sum[y] += sum[x];
    }
    
    int main(){
        cin >> n;
        for (int i = 1; i <= n; i++) {
            par[i] = i;
            scanf("%lld", a + i);
            sum[i] = a[i];
        }
        for (int i = 1; i <= n; i++)
            scanf("%d", b + i);
        LL res = 0;
        for (int i = n; i >= 1; i--){
            ans[i] = res;
            if (vis[b[i] + 1]) unite(b[i], b[i] + 1);
            if (vis[b[i] - 1]) unite(b[i], b[i] - 1);
            vis[b[i]] = true;
            res = max(res, sum[pfind(b[i])]);
        }
        for (int i = 1; i <= n; i++)
            cout << ans[i] << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    第3次作业卷积神经网络
    SpringCloud Sidecar 整合.Net WebApi
    redefinition of class解决
    DP学习笔记
    NOIP2018 Day2毒瘤题目
    NOIP Day1总结
    关于DP
    这次的PION的总结
    NOIP模拟赛D2T1自己的解题思路
    ABAP Editor自动完成功能
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5927270.html
Copyright © 2011-2022 走看看