zoukankan      html  css  js  c++  java
  • hdu 1540 Tunnel Warfare (线段树维护左右最长连续区间)

    题意是一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
    线段树结点 设置一个 ll 记录区间左端点开始的最大连续个数, rl 记录区间右端点开始的最大的连续个数,
    ml表示该区间最大的连续点的个数。

    主要是更新和查询两个操作。

    /*
    key: ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度

    求与某点相连的连续最长距离。
    线段树优化了求连续最长的时间,枚举是O(n),线段树O(log2[n])
    */

    #include <cstdio>
    #include <stack>
    using namespace std;

    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define N 50005

    int max3(int x, int y, int z)
    {
        x = x > y ? x : y;
        return z > x ? z : x;
    }

    struct Seq
    {
        int ll,rl,ml;//左起最大长度,右起最大长度,区间最大长度
    }seq[N<<2];

    stack<int> st;

    void build(int l, int r, int rt)
    {
        if(l==r)
            seq[rt].ml = seq[rt].ll = seq[rt].rl = 1;
        else
        {
            int m = (l + r) >> 1;
            build(lson);
            build(rson);
            seq[rt].ml = seq[rt].ll = seq[rt].rl = seq[rt<<1].ml + seq[rt<<1|1].ml;
        }
    }

    void update(int i, int add, int l, int r, int rt)
    {
        if(l==r)
        {
            seq[rt].ml = add;
            seq[rt].ll = seq[rt].rl = seq[rt].ml;
        }
        else
        {
            int m = (l + r) >> 1;
            if(i<=m)
                update(i, add, lson);
            else
                update(i, add, rson);
            seq[rt].ll = seq[rt<<1].ll;
            if(m-l+1== seq[rt<<1].ml)//左孩子区间最大长度等于区间长度
                seq[rt].ll += seq[rt<<1|1].ll;
            seq[rt].rl = seq[rt<<1|1].rl;
            if(r - m == seq[rt<<1|1].ml)//右孩子区间最大长度等于区间长度
                seq[rt].rl += seq[rt<<1].rl;
            //父亲节点区间最大长度 为 max(左孩子右起最大长度+右孩子左起最大长度 ,左孩子区间最大长度,右孩子区间最大长度)
            seq[rt].ml = max3(seq[rt<<1].ml, seq[rt<<1|1].ml, seq[rt<<1].rl+seq[rt<<1|1].ll);
        }
    }

    int query(int pos, int l, int r, int rt)
    {
        if(l==r || seq[rt].ml==0 || seq[rt].ml == r - l + 1)//叶子节点 或 区间最大长度等0 或 区间最大长度等于整个区间长度
            return seq[rt].ml;
        else
        {
            int m = (l + r) >> 1;
            int ret = 0;
            if(pos<=m)//查找点在左子树
            {
                ret = query(pos, l, m, rt<<1);
                if(pos > m - seq[rt<<1].rl)//查找点在右起第一断点的右边
                    ret += seq[rt<<1|1].ll;
            }
            else//在右子树
            {
                ret = query(pos, m+1, r, rt<<1|1);
                if(pos < m + 1 + seq[rt<<1|1].ll)//查找点在左起第一断点的左边
                    ret += seq[rt<<1].rl;
            }
            return ret;
        }
    }

    int main()
    {
        int n, m, x;
        char s[5];
        while(scanf("%d%d", &n, &m)!=EOF)
        {
        build(1, n, 1);
        while(!st.empty()) st.pop();
        for(int i=1; i<=m; i++)
        {
            scanf("%s",s);
            if(s[0]=='D')
            {
                scanf("%d",&x);
                update(x, 01, n, 1);
                st.push(x);
            }
            else if(s[0]=='R')
            {
                x = st.top();
                st.pop();
                update(x, 11, n, 1);
            }
            else if(s[0]=='Q')
            {
                scanf("%d",&x);
                printf("%d ",query(x, 1, n, 1));
            }
        }
        }
        return 0;
    }
    View Code 
  • 相关阅读:
    Luogu P5030 长脖子鹿放置(网络流)
    BZOJ3037 创世纪(基环树DP)
    LuoguP1240 诸侯安置
    LuoguP3128 [USACO15DEC]最大流Max Flow (树上差分)
    总结-一本通提高篇&算竞进阶记录
    LuoguP5022 旅行 (割点,基环树)
    $tsinsenA1067$
    $SCOJ4427 Miss Zhao's Graph$
    $Edmonds-Karp$[网络流]
    $AC自动机$
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3418498.html
Copyright © 2011-2022 走看看