Tunnel Warfare(线段树 + 区间合并)

本文深入探讨了中国东北平原上,抗日战争时期隧道战的广泛运用。文章详细介绍了村庄通过隧道相连的布局特点,以及敌军攻击村庄、破坏隧道后,八路军司令部对当前隧道连接状态的迫切需求。通过对不同格式事件的处理,包括摧毁村庄、请求查询连接村庄数量及重建村庄等,展示了线段树和区间合并技术在解决实际问题中的应用。

Tunnel Warfare

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4070    Accepted Submission(s): 1526


Problem Description
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

      题意:

      给出 n,m(1 ~ 50000),代表有 n 个连续的城市 和 m 个操作,操作有 3 类,D ans,代表要把编号为 ans 的城市毁灭,R 代表要重建最后毁灭的那么 城市,Q ans 代表询问包含 ans 的完好的连续城市有几个。每次 Q 给出一个结果。

  

      思路:

      线段树,区间合并。注意 updata 的时候要判断往左还是往右,如果不判断的话,则会 TLE。

 

      AC:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>

using namespace std;

const int MAX = 500050;

int lmax[MAX], rmax[MAX], mmax[MAX];

void push_up(int node, int l, int r) {
        lmax[node] = lmax[node << 1];
        rmax[node] = rmax[node << 1 | 1];

        int mid = (r + l) >> 1;
        if (lmax[node] == mid - l + 1) lmax[node] += lmax[node << 1 | 1];
        if (rmax[node] == r - mid) rmax[node] += rmax[node << 1];

        mmax[node] = max(rmax[node << 1] + lmax[node << 1 | 1],
                         max(mmax[node << 1], mmax[node << 1 | 1]));
}

void build (int node, int l, int r) {
        if (l == r) {
                lmax[node] = rmax[node] = mmax[node] = 1;
        } else {
                int mid = (r + l) >> 1;
                build(node << 1, l, mid);
                build(node << 1 | 1, mid + 1, r);
                push_up(node, l, r);
        }
}

void update(int node, int l, int r, int loc, int s) {
        if (l == r) {
                if (l == loc) {
                        mmax[node] = lmax[node] =
                        rmax[node] = (s ? 0 : 1);
                }
                return;
        }

        int mid = (r + l) >> 1;
        if (loc <= mid) update(node << 1, l, mid, loc, s);
        else update(node << 1 | 1, mid + 1, r, loc, s);
        push_up(node, l, r);
}

int query (int node, int l, int r, int loc) {
        int mid = (r + l) >> 1;

        if (mmax[node] == r - l + 1 || !mmax[node])
            return mmax[node];

        if (loc <= mid) {
                if (loc >= mid - rmax[node << 1] + 1)
                        return query(node << 1, l, mid, loc) +
                               query(node << 1 | 1, mid + 1, r, mid + 1);
                else return query(node << 1, l, mid, loc);
        } else {
                if (loc <= mid + 1 + lmax[node << 1 | 1] - 1)
                        return query(node << 1, l, mid, mid) +
                               query(node << 1 | 1, mid + 1, r, loc);
                else return query(node << 1 | 1, mid + 1, r, loc);
        }
}

int main() {
        int n, m;

        while(~scanf("%d%d", &n, &m)) {
                stack<int> s;

                build (1, 1, n);

                while (m--) {
                        char op;
                        scanf(" %c", &op);

                        if (op == 'D') {
                                int loc;
                                scanf("%d", &loc);
                                update(1, 1, n, loc, 1);
                                s.push(loc);
                        } else if (op == 'Q') {
                                int loc;
                                scanf("%d", &loc);

                                printf("%d\n", query(1, 1, n, loc));

                        } else {
                                int loc = s.top();
                                s.pop();
                                update(1, 1, n, loc, 0);
                        }
                }

        }

        return 0;
}

 

<think> 嗯,用户想了解思科设备上的IPv6隧道配置方法。参考提供的资料,发现主要有三种隧道技术:GRE隧道、ISATAP隧道和Manual隧道。其中引用[1]详细描述了GRE隧道的实验配置步骤,引用[3]则重点介绍了ISATAP隧道,而引用[4]提到了IPv6 Manual隧道的验证命令。 用户可能是网络工程师或备考认证的学习者,需要具体配置指导而非理论概述。考虑到实际应用场景,应该突出不同隧道的适用条件:GRE适合站点间固定连接,ISATAP用于主机到路由器的自动隧道,Manual隧道则用于简单点对点连接。 在整理配置步骤时,要注意几点:一是所有接口必须激活IPv6路由功能;二是隧道模式选择很关键,比如GRE模式是"ipv6ip",而ISATAP是"ipv6ip isatap";三是源地址通常用环回口确保稳定性。引用[5]提到的RFC标准也值得强调,说明这些技术的规范性。 安全方面需要提醒用户,这些隧道本身不加密,引用[2]提到IPv6安全性时暗示了这一点。因此补充了IPsec的应用建议,这虽然超出当前问题范围,但对实际部署很重要。 最后生成的问题覆盖了排错、协议选择和迁移场景,特别是"自动建立隧道"这点来自引用[3]里ISATAP的实验分析,用户如果遇到邻居发现失败的问题可能需要进一步研究NDP报文。 </think> 以下是思科设备上配置 IPv6 隧道的详细方法,综合参考了站内引用信息: ### 一、主要隧道技术及配置要点 1. **GRE隧道(通用路由封装)** - **原理**:在IPv4网络上封装IPv6数据包(引用[1][5]) - **配置步骤**: ```cisco ! 创建隧道接口 interface Tunnel0 ipv6 enable ! 启用IPv6 ipv6 address <隧道IPv6地址> ! 配置隧道接口IPv6地址 tunnel source <本地IPv4地址> ! 指定隧道源地址(如物理接口或Loopback) tunnel destination <对端IPv4地址> ! 指定隧道目标地址 tunnel mode gre ipv6 ! 设置隧道模式(引用[1][4]) ``` **关键验证命令**: `show ipv6 interface brief`(检查隧道状态,引用[4]) `show ipv6 route`(验证路由学习) 2. **ISATAP隧道(站内自动隧道寻址协议)** - **特点**:支持主机自动建立隧道(引用[3]) - **配置核心**: ```cisco interface Tunnel0 ipv6 address autoconfig ! 自动配置地址 tunnel source <本地IPv4地址> tunnel mode ipv6ip isatap ! 指定ISATAP模式 ``` **自动建立机制**: 通过NDP(邻居发现协议)和特定格式的IPv6地址(`Prefix:0:5EFE:IPv4地址`)实现自动隧道建立(引用[3]) 3. **手动隧道(Manual Tunnel)** - **适用场景**:点对点简单连接 ```cisco interface Tunnel10 ipv6 address <手动指定IPv6地址> tunnel source <本地IPv4地址> tunnel destination <对端IPv4地址> tunnel mode ipv6ip ! 标准IPv6-over-IPv4模式 ``` ### 二、通用配置注意事项 1. **基础准备** - 启用全局IPv6路由:`ipv6 unicast-routing` - 配置底层IPv4连通性(必备条件) 2. **路由协议集成** - 在隧道接口启用OSPFv3等路由协议(引用[1][3]): ```cisco interface Tunnel0 ospfv3 1 ipv6 area 0 ! 示例:OSPFv3配置 ``` 3. **隧道稳定性优化** - 使用Loopback接口作源地址: ```cisco tunnel source Loopback0 ``` - 调整MTU:`ipv6 mtu 1400`(避免分片) ### 三、验证与排错命令 | **命令** | **作用** | 引用来源 | |-----------------------------------|-----------------------------|-----------| | `show ipv6 interface tunnel X` | 检查隧道状态和配置 | [1][3][4] | | `ping ipv6 <隧道对端地址>` | 测试隧道连通性 | [1][3] | | `debug tunnel` | 实时诊断隧道建立问题 | [4] | | `show ospfv3 neighbor` | 验证OSPFv3邻接关系 | [1] | > **关键提醒**: > - GRE和手动隧道需**静态指定**对端IPv4地址,ISATAP支持动态发现(引用[3][5]) > - 跨NAT场景需额外配置(多数隧道不支持NAT穿透) > - 生产环境建议结合IPsec加密(引用[2]中提到的安全性要求)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值