• Tunnel Warfare--- hdu1540 线段树求连续子区间


    题目链接

    题意:有n个村庄,编号分别为1-n;由于战争会破坏村庄,但是我们也会修复;

    D x代表村庄x被破坏;

    Q x是求与x相连的有几个没有被破坏;

    R 是修复最后一次被破坏的村庄;

    接下来有m个操作,对于每次Q操作输出结果;

    由于修复的是最后一次被破坏的所以要用stack

     

    接下来看代码吧,加个图好理解一点

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stack>
    using namespace std;
    
    #define INF 0xfffffff
    #define N 50050
    #define Lson r<<1
    #define Rson r<<1|1
    
    struct SegmentTree
    {
        int L, R, sum, lsum, rsum;
    
        int Mid() { return (L+R)>>1;}
        int len() { return R-L+1; }
    
    } a[N<<2];
    
    void Build(int r, int L, int R)
    {
        a[r].L = L, a[r].R = R;
        a[r].sum = a[r].lsum = a[r].rsum = a[r].len();///刚开始的时候一定是区间所在长度;
        if(L == R) return;
        Build(Lson, L, a[r].Mid());
        Build(Rson, a[r].Mid()+1, R);
    }
    
    void Up(int r)///当下面的节点发生变化的时候我们要往上不断更新
    {
        a[r].lsum = a[Lson].lsum;
        a[r].rsum = a[Rson].rsum;
    
        if(a[r].lsum == a[Lson].len())
            a[r].lsum += a[Rson].lsum;
        if(a[r].rsum == a[Rson].len())
            a[r].rsum += a[Lson].rsum;
    
        a[r].sum = max(max(a[Lson].lsum, a[Rson].rsum),a[Lson].rsum+a[Rson].lsum);
    }
    
    void Update(int r, int pos, int flag)///flag 为0表示破坏,1表示修复;
    {///因为是直接更新到叶子节点的所以不需再往下更新,但是要往上更新;
        if(a[r].L == a[r].R && a[r].L==pos)
        {
            a[r].sum = a[r].lsum = a[r].rsum = flag;
            return ;
        }
    
        if(pos <= a[r].Mid())
            Update(Lson, pos, flag);
        else if(pos > a[r].Mid())
            Update(Rson, pos, flag);
    
        Up(r);
    }
    
    int Query(int r, int pos)
    {
        if(a[r].sum == 0)return 0;
    
        if(pos < a[r].L + a[r].lsum) return a[r].lsum;///在最左边
        if(pos > a[r].R - a[r].rsum) return a[r].rsum;///在最右边
    
        if(pos > a[Lson].R - a[Lson].rsum && pos < a[Rson].L + a[Rson].lsum )///在中间部分;
            return a[Lson].rsum + a[Rson].lsum;
    
        if(pos <= a[r].Mid()) return Query(Lson, pos);///在左半边而非最左边;
        else return Query(Rson, pos);///在右半边而非最右边;
    }
    
    int main()
    {
        int n, m, x;
        char s[110];
        while(scanf("%d %d", &n, &m)!=EOF)
        {
            Build(1, 1, n);
            stack<int> sta;
            for(int i=1; i<=m; i++)
            {
                scanf("%s", s);
                if(s[0] == 'D')
                {
                    scanf("%d", &x);
                    Update(1, x, 0);
                    sta.push(x);///按破坏顺序一个一个的加入栈中
                }
                else if(s[0] == 'Q')
                {
                    scanf("%d", &x);
                    printf("%d
    ", Query(1, x));
                }
                else
                {
                    x = sta.top();
                    sta.pop();
                    Update(1, x, 1);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    洛谷5495:Dirichlet前缀和
    SP5971 LCMSUM
    洛谷1829:crash的数字表格
    洛谷3172:选数
    Codeforces 1295 D. Same GCDs
    洛谷3768:简单的数学题
    NTT学习笔记
    洛谷1169:棋盘制作(悬线法)
    洛谷2444:病毒
    后缀自动机
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4693890.html
Copyright © 2020-2023  润新知