zoukankan      html  css  js  c++  java
  • Tunnel Warfare HDU

    题意:

    一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
     
    解析:
    线段树结点 设置一个  lq记录区间左端点开始的最大连续个数,  rq 记录区间右端点开始的最大的连续个数
    其它和原来一样即可
    看代码吧。。。
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #define mem(a, b) memset(a, b, sizeof(a))
    using namespace std;
    const int maxn = 1000010, INF = 0x7fffffff;
    typedef long long LL;
    int a, b, x, y, ans;
    
    struct node{
        int l, r, w, lq, rq;
    }Node[maxn];
    
    void build(int k, int ll, int rr)
    {
        Node[k].l = ll, Node[k].r = rr;
        if(Node[k].l == Node[k].r)
        {
            Node[k].lq = Node[k].rq = Node[k].w = 1;
            return;
        }
        int m = (ll + rr) / 2;
        build(k*2, ll, m);
        build(k*2+1, m+1, rr);
        Node[k].lq = Node[k].rq = Node[k].w = Node[k*2].w + Node[k*2+1].w;
    }
    
    void chp(int k)  //单点修改
    {
        if(Node[k].l == Node[k].r)
        {
            Node[k].lq = Node[k].rq = Node[k].w = y;
            return;
        }
        int m = (Node[k].l + Node[k].r) / 2;
        if(x <= m) chp(k*2);
        else chp(k*2+1);
        Node[k].w = Node[k*2].w + Node[k*2+1].w;
        Node[k].lq = Node[k*2].lq;           //修改后初始化 父结点的最长连续左区间 为 左子结点的最长连续左区间
        Node[k].rq = Node[k*2+1].rq;         //父结点的最长连续右区间 为 右子结点的最长连续右区间
        if(Node[k*2].lq == Node[k*2].r - Node[k*2].l + 1)  //如果左子结点的最长连续左区间 为整个区间的长度 那么父结点的最长连续左区间 应该 加上 右子结点的最长连续右区间
            Node[k].lq += Node[k*2+1].lq;
        if(Node[k*2+1].rq == Node[k*2+1].r - Node[k*2+1].l + 1) // 同理
            Node[k].rq += Node[k*2].rq;
    }
    
    void qinter(int k, int t)
    {
        if(Node[k].l == Node[k].r || Node[k].w == 0 || Node[k].w == Node[k].r - Node[k].l + 1) //如果当前区间为单点、区间和为0、区间和为区间长度 那么就没必要往下搜了 返回即可
        {
            ans += Node[k].w;
            return;
        }
        int m = (Node[k].l + Node[k].r) / 2;
        if(t <= m)   //如果t在左子树
        {
            if(t >= Node[k*2].r - Node[k*2].rq + 1)  //如果t大于左子树右区间的左端点 说明t在左子树的右区间内
            {
                ans += (Node[k*2].rq + Node[k*2+1].lq);  //然后用左子树的最长连右区间 + 右子树的最长连续左区间
                return;
            }
            else
                qinter(k*2, t);  //如果不在右区间 则向下搜
        }
        else //同理
        {
            if(t <= Node[k*2+1].l + Node[k*2+1].lq - 1)
            {
                ans += (Node[k*2+1].lq + Node[k*2].rq);
                return;
            }
            else
                qinter(k*2+1, t);
        }
    }
    
    int main()
    {
        int n, m;
        ans = 0;
       while(~scanf("%d%d",&n,&m)){
            build(1, 1, n);
            stack<int> G;
            getchar();
            for(int i=0; i<m; i++)
            {
                char str[1010];
                scanf("%s",str);
                if(strcmp(str, "D") == 0)
                {
                    scanf("%d",&x);
                    G.push(x);
                    y = 0;
                    chp(1);
                }
                else if(strcmp(str, "R") == 0)
                {
                    x = G.top();
                    G.pop();
                    y = 1;
                    chp(1);
                }
                else if(strcmp(str, "Q") == 0)
                {
                    scanf("%d",&x);
                    ans = 0;
                    qinter(1, x);
                    printf("%d
    ",ans);
                }
    
            }
       }
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    Python模块之pysnooper
    本站页脚HTML回顶部代码
    本站CSS代码
    Linux使用 tar命令-g参数进行增量+差异备份、还原文件
    mysql定时备份shell脚本
    Linux系统备份与还原
    MYSQL备份与恢复
    技术普及帖:你刚才在淘宝上买了一件东西
    Linux运维工程师前景
    Linux运维工程师需掌握的技能
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9244787.html
Copyright © 2011-2022 走看看