zoukankan      html  css  js  c++  java
  • hdu1540 Tunnel Warfare【线段树】

    During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones. 

    Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately! 

    Input

    The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event. 

    There are three different events described in different format shown below: 

    D x: The x-th village was destroyed. 

    Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself. 

    R: The village destroyed last was rebuilt. 

    Output

    Output the answer to each of the Army commanders’ request in order on a separate line. 

    Sample Input

    7 9
    D 3
    D 6
    D 5
    Q 4
    Q 5
    R
    Q 4
    R
    Q 4

    Sample Output

    1
    0
    2
    4

    区间合并

    用Ltree 和Rtree分别存【L,R】区间中从L开始到右侧最长的连续区间长度 和从R开始到左侧最长的连续区间长度

    pushup的时候需要比较左孩子的Ltree能不能和右孩子的相连 右孩子的Rtree能不能和左孩子的相连

    destroy 和rebuilt 都是对点进行更新

    query的时候,我们和单点查询一样,直到找到当前点的叶子节点一路查询即可。

    这里重点在于区间合并的操作,首先我们讨论当前区间点的问题:

    如果当前区间点从左到右能够覆盖查询点,那么ans=max(ans,Lsum【now】);

    同理,如果当前区间从右到左能够覆盖查询点,那么ans=max(ans,Rsum【now】);

    然后我们讨论当前区间和兄弟节点的合并查询问题:

    如果当前区间点是左儿子,那么对应我们查询左儿子的Rsum和右儿子的Lsum是否能够连接并且覆盖查询点,如果可以,那么对应ans=max(ans,Rsum【now】+Lsum【now+1】)

    如果当前区间点是右儿子,那么对应我们查询右儿子的Lsum和左儿子的Rsum是否能够连接并且覆盖查询点,如果可以,那么对应ans=max(ans,Lsum【now】+Rsum【now-1】);

    
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stack>
    #define inf 1e18
    using namespace std;
    
    int m, n;
    const int maxn = 50005;
    int Ltree[maxn << 2], Rtree[maxn<<2];
    
    void pushup(int l, int r, int rt)//更新
    {
        Ltree[rt] = Ltree[rt * 2];
        Rtree[rt] = Rtree[rt * 2 + 1];
        int m = (l + r) / 2;
        if(Ltree[rt * 2] == (m - l + 1))Ltree[rt] += Ltree[rt * 2 + 1];
        if(Rtree[rt * 2 + 1] == (r - m))Rtree[rt] += Rtree[rt * 2];
    
    }
    
    void build(int l, int r, int rt)
    {
        if(l == r){
            Ltree[rt] = Rtree[rt] = l - r + 1;
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
        pushup(l, r, rt);
    }
    
    
    void update(int L, int C, int l, int r, int rt)
    {
        if(l == r){
            if(C == -1){
                Ltree[rt] = Rtree[rt] = 0;
            }
            else{
                Ltree[rt] = Rtree[rt] = 1;
            }
            return;
        }
        int m = (l + r) >>1;
        if(L <= m) update(L, C, l, m, rt << 1);
        else update(L, C, m + 1, r, rt << 1 | 1);
        pushup(l, r, rt);
    }
    
    /*void update(int L, int R, int l, int r, int rt)
    {
        if(tree[rt] == r - l + 1){//本区间完全在操作区间内
            return;
        }
        if(l == r){
            tree[rt] = sqrt(tree[rt]);
            return;
        }
        int m = (l + r) >> 1;
        if(L <= m) update(L, R, l, m, rt << 1);
        if(R > m) update(L, R, m + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    */
    int query(int L, int l, int r, int rt)
    {
        if(l == r){
            return max(Ltree[rt], Rtree[rt]);
        }
        pushup(l, r, rt);
        int m = (l + r) >> 1;
        //pushdown(rt, m - l + 1, r - m);
    
        int ans = 0;
        if(L >= l && L <= r){
            if(Ltree[rt] >= L - l + 1)
                ans = max(ans, Ltree[rt]);
            if(Rtree[rt] >= r - L + 1)
                ans = max(ans, Rtree[rt]);
        }
        if(rt % 2 == 0){
            if(Rtree[rt] >= r - L + 1)
                ans = max(ans, Rtree[rt] + Ltree[rt + 1]);
        }
        else{
            if(Ltree[rt] >= L - l + 1)
                ans = max(ans, Ltree[rt] + Rtree[rt - 1]);
        }
        if(L <= m)
            ans = max(ans, query(L, l, m, rt << 1));
        if(L > m)
            ans = max(ans, query(L, m + 1, r, rt << 1|1));
        pushup(l, r, rt);
        return ans;
    }
    
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF){
            stack<int>des;
            build(1, n, 1);
            for(int i = 0; i < m; i++){
                getchar();
                char ch;
                int a;
                scanf("%c", &ch);
                if(ch == 'R'){
                    if(des.size() == 0)continue;
                    a = des.top();des.pop();
                    update(a, 1, 1, n, 1);
                }
                else{
                    scanf("%d", &a);
                    if(ch == 'D'){
                        des.push(a);
                        update(a, -1, 1, n, 1);
                    }
                    else{
                        printf("%d
    ", query(a, 1, n, 1));
                    }
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    使用 udev 高效、动态地管理 Linux 设备文件
    【技术贴】visual stdio 2005下载地址,vs2005下载地址 vs2005正版破解 v
    【转】无法登陆SQL server 服务器的解决办法
    【技术贴】visual stdio 2005下载地址,vs2005下载地址 vs2005正版破解 v
    【技术贴】远程桌面连接 时“由于帐户限制 您无法登陆”的解决办法
    【转】桌面快捷方式打不开的解决办法
    【技术贴】从51下载的网站代码asp源码怎么运行?怎么打开?
    【转】Visual Studio 2005不能调试的错误
    【技术贴】asms文件,安装windows xp原版时,需要“asms”文件,H:\I386\asm
    【技术贴】asms文件,安装windows xp原版时,需要“asms”文件,H:\I386\asm
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9643394.html
Copyright © 2011-2022 走看看