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 
  • 相关阅读:
    WCF Server Console
    Restart IIS With Powershell
    RestartService (recursively)
    Copy Files
    Stopping and Starting Dependent Services
    多线程同步控制 ManualResetEvent AutoResetEvent MSDN
    DTD 简介
    Using Powershell to Copy Files to Remote Computers
    Starting and Stopping Services (IIS 6.0)
    java中的NAN和INFINITY
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3418498.html
Copyright © 2011-2022 走看看