zoukankan      html  css  js  c++  java
  • hdu 3911 Black And White(线段树)

    题目连接:hdu 3911 Black And White

    题目大意:给定一个序列,然后有M次操作;

    • 0 l r:表示询问l,r中最大连续1的个数
    • 1 l r:表示将l,r区间上的数取反

    解题思路:线段树的一种题型,区间合并,由于有一个取反的操作,所以对于每一个节点要维护6个值,包含连续0,1最长序列的长度,左边和右边的最长连续长度。须要注意的是,假设询问的区间最大值是从R[lson] + L[rson]来到,要推断是否比长度大于r - l + 1。一開始没注意,所以WA了,上网搜了下别人的题解,发现非常多人在query里面没有pushup更新当前节点信息,这样肯定是不行的,有pushdown,肯定要在更新当前节点信息的。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1e5 + 5;
    
    int N, M, a[maxn];
    
    #define lson(x) ((x)<<1)
    #define rson(x) (((x)<<1)|1)
    int lc[maxn << 2], rc[maxn << 2], filp[maxn << 2];
    int L[maxn << 2][2], R[maxn << 2][2], S[maxn << 2][2];
    
    void maintain (int u) {
        filp[u] ^= 1;
        swap(L[u][0], L[u][1]);
        swap(R[u][0], R[u][1]);
        swap(S[u][0], S[u][1]);
    }
    
    void pushup(int u) {
        for (int i = 0; i < 2; i++) {
            S[u][i] = max(max(S[lson(u)][i], S[rson(u)][i]), R[lson(u)][i] + L[rson(u)][i]);
            L[u][i] = L[lson(u)][i] + (L[lson(u)][i] == rc[lson(u)] - lc[lson(u)] + 1 ? L[rson(u)][i] : 0);
            R[u][i] = R[rson(u)][i] + (R[rson(u)][i] == rc[rson(u)] - lc[rson(u)] + 1 ? R[lson(u)][i] : 0);
        }
    }
    
    void pushdown (int u) {
        if (filp[u]) {
            maintain(lson(u));
            maintain(rson(u));
            filp[u] = 0;
        }
    }
    
    void build (int u, int l, int r) {
        lc[u] = l;
        rc[u] = r;
        filp[u] = 0;
    
        if (l == r) {
            int d = a[l];
            L[u][d] = R[u][d] = S[u][d] = 1;
            L[u][d^1] = R[u][d^1] = S[u][d^1] = 0;
            return ;
        }
    
        int mid = (l + r) / 2;
        build(lson(u), l, mid);
        build(rson(u), mid+1, r);
        pushup(u);
    }
    
    void modify (int u, int l, int r) {
        if (l <= lc[u] && rc[u] <= r) {
            maintain(u);
            return;
        }
    
        pushdown(u);
        int mid = (lc[u] + rc[u]) / 2;
        if (l <= mid)
            modify(lson(u), l, r);
        if (r > mid)
            modify(rson(u), l, r);
        pushup(u);
    }
    
    int query (int u, int l, int r) {
        if (l <= lc[u] && rc[u] <= r)
            return S[u][1];
    
        pushdown(u);
        int mid = (lc[u] + rc[u]) / 2, ret;
        if (r <= mid)
            ret = query(lson(u), l, r);
        else if (l > mid)
            ret = query(rson(u), l, r);
        else {
            int ll = query(lson(u), l, r);
            int rr = query(rson(u), l, r);
    
            int a = min(L[rson(u)][1], r - mid);
            int b = min(R[lson(u)][1], mid - l + 1);
    
            ret = max( max(ll, rr), a + b);
        }
        pushup(u);
        return ret;
    }
    
    int main () {
        int x, l, r;
    
        while (scanf("%d", &N) == 1) {
            for (int i = 1; i <= N; i++)
                scanf("%d", &a[i]);
            build (1, 1, N);
    
            scanf("%d", &M);
            while (M--) {
                scanf("%d%d%d", &x, &l, &r);
                if (x)
                    modify(1, l, r);
                else
                    printf("%d
    ", query(1, l, r));
            }
        }
        return 0;
    }
  • 相关阅读:
    学习asp.net比较完整的流程
    [图像思考法]我用图像故事法来理解与记忆冒泡排序
    MVC4与JSON交互的知识总结
    vulhub漏洞环境库内容整理
    kaliapt update时报The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ED444FF07D8D0BF6解决方案
    sqlilabs靶机测试笔记
    Lord_Of_The_Root1.0.1靶机测试笔记
    utf16的单引号乱码,用于post型宽字节注入
    ubuntu16.04报错AttributeError: module 'platform' has no attribute 'linux_distribution'
    一文搞定OSCP的缓冲区溢出
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4059736.html
Copyright © 2011-2022 走看看