bzoj4523【CQOI2016】路由表

4523: [Cqoi2016]路由表

Time Limit: 30 Sec  Memory Limit: 512 MB

Submit: 213  Solved: 134

[Submit][Status][Discuss]

Description

路由表查找是路由器在转发IP报文时的重要环节。通常路由表中的表项由目的地址、掩码、下一

跳(Next Hop)地址和其他辅助信息组成。例如:

当路由器收到一个IP报文时,会将报文中的目的IP地址与路由表中的表项逐条进行比较,选

择匹配且最明确的表项,将报文转发给该表项中指定的下一跳。

匹配的过程是将报文中的目的地址和表项中的目的地址分别转为二进制串,再查看表项中的掩

码长度,若掩码长度为x,则将两个二进制串的前x位进行比较,如果相同则认为匹配。

所谓最明确是指在有多个表项匹配时,总是掩码长度最大的表项。也可以理解为匹配的二进制

位最多的项。

IP地址转为二进制串的操作是把地址中4个整数(一定在y到255的范围内)分别转为8位

二进制数,再顺序拼接起来,得到一个32位的二进制串。例如,192.168.1.253转为二进制串后为

11000000 10101000 00000001 11111101

我们以报文的目的地址为8.8.8.8为例,说明其在上述路由表的匹配过程。

上表将地址均转为二进制串,并用红色标记出待比较的位(由掩码长度决定)。将红色部分与

报文中的目的地址比较,可知0.0.0.0/1、8.8.8.0/24、8.8.8.8、32均能够匹配。路由器从中选取掩

码长度最长(/32)的表项8.8.8.8/32,将报文转发给其对应的下一跳地址192.168.1.253。

在实际的核心路由器中,路由表通常较大(现在互联网的全局路由表已经接60万条记录),

并且会随着新接入设备不断扩张。为了分析路由表变化对转发产生的影响,网络工程师想要知道

一段时间内某个IP地址的路由表项选择发生了多少次变化(变化是指由于最明确匹配等因素选择

了不同的表项,不考虑下一跳地址)。

Input

第一行为整数M,表示共有M次操作。接下来M行,每行描述一次操作。操作有两种:

A D/L

其中.为一个IP地址,G为整数(1≤L≤32)。添加一条表项至路由表,其目的地址为

D掩码长度为L。下一跳地址由于没有用到,故省略。

Q D a b

其中D为一个IP地址,a,b为正整数(a≤b)。查询从第a次至第b次添加表项期间(含

a、b),目的地址D的路由表项选择发生了多少次变化。保证查询时表中至少有b个表项。

N<=10^6数据保证不会重复添加目的地址和掩码长度都相同的表项。

Output

包含若干行,每行仅有一个整数,依次对应每个查询操作。

Trie树乱搞

天哪,这数据给的太良心了!

将所有字符串插入Trie树中,在结束为止记录一个时间戳。

然后对于每组询问,将Trie树上那一条链的信息拿出来,然后随便乱搞一下就可以了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define N 33000000
using namespace std;
int n,cnt=1,tot;
int a[50],b[50],c[N][2],tag[N];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void add()
{
	int x,len,now=1;
	F(i,0,3)
	{
		x=read();
		D(j,8,1) a[j+i*8]=x&1,x>>=1;
	}
	len=read();
	F(i,1,len)
	{
		if (!c[now][a[i]]) c[now][a[i]]=++cnt;
		now=c[now][a[i]];
	}
	tag[now]=++tot;
}
void query()
{
	int x,l,r,len=0,now=1;
	F(i,0,3)
	{
		x=read();
		D(j,8,1) a[j+i*8]=x&1,x>>=1;
	}
	l=read();r=read();
	F(i,1,32)
	{
		if (!c[now][a[i]]) break;
		now=c[now][a[i]];
		if (tag[now]&&tag[now]<l) len=0;
		if (tag[now]>=l&&tag[now]<=r)
		{
			while (len&&b[len]>=tag[now]) len--;
			b[++len]=tag[now];
		}
	}
	printf("%d\n",len);
}
int main()
{
	n=read();
	F(i,1,n)
	{
		char ch=getchar();while (ch!='A'&&ch!='Q') ch=getchar();
		if (ch=='A') add();
		else query();
	}
	return 0;
}
时间: 2024-10-09 00:53:04

bzoj4523【CQOI2016】路由表的相关文章

【BZOJ4523】[Cqoi2016]路由表 Trie树模拟

[BZOJ4523][Cqoi2016]路由表 Description 路由表查找是路由器在转发IP报文时的重要环节.通常路由表中的表项由目的地址.掩码.下一跳(Next Hop)地址和其他辅助信息组成.例如: 当路由器收到一个IP报文时,会将报文中的目的IP地址与路由表中的表项逐条进行比较,选择匹配且最明确的表项,将报文转发给该表项中指定的下一跳. 匹配的过程是将报文中的目的地址和表项中的目的地址分别转为二进制串,再查看表项中的掩码长度,若掩码长度为x,则将两个二进制串的前x位进行比较,如果相

【BZOJ-4523】路由表 Trie树 + 乱搞

4523: [Cqoi2016]路由表 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 155  Solved: 98[Submit][Status][Discuss] Description 路由表查找是路由器在转发IP报文时的重要环节.通常路由表中的表项由目的地址.掩码.下一跳(Next Hop)地址和其他辅助信息组成.例如: 当路由器收到一个IP报文时,会将报文中的目的IP地址与路由表中的表项逐条进行比较,选择匹配且最明确的表项,将报文转发给

[BZOJ4523]路由表

对于每一条询问,我们可以通过一个数组维护第一次匹配长度为i时的插入时间来计算在[l,r]中改变了多少遍 由于现在长度已经单调,选择会发生变化当且仅当时间也单调, 于是我们可以通过单调栈计算[1,x]中改变了多少遍 ans=solve(r)-solve(l-1) 对于多个询问,我们可以把询问插入trie树中,实现多个询问共用一个维护数组 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #defi

【CQOI2016纯净整合】BZOJ-4519~4524 (5/6)

感觉CQOI的难度挺好的,比较贴近自身,所以拿出来做了一下 CQOI2016 Day1 T1:不同的最小割 涉及算法:最小割/分治/最小割树 思路: 最小割树裸题,直接分治最小割,记录下答案,最后排序一下,统计不同的答案即可 CODE: #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace

centos7系统设置vpn连接及查看设置路由表router

一.设置vpn客户端连接 1.1安装软件包ppp/pptp/pptp-setup yum -y install ppp pptp pptp-setup 1.2.创建vpn连接的配置文件 pptpsetup --create<定义的名称> --server<服务器>  --username <用户名> --password <密码> [--start] <>必填,[]可选 pptpsetup --create HK_VPN --server x.x

CentOS添加路由表

CentOS下静态路由修改命令方法一:添加路由route add -net 192.168.0.0/24 gw 192.168.0.1route add -host 192.168.1.1 dev 192.168.0.1删除路由route del -net 192.168.0.0/24 gw 192.168.0.1 add 增加路由del 删除路由-net 设置到某个网段的路由-host 设置到某台主机的路由gw 出口网关 IP地址dev 出口网关 物理设备名 增 加默认路由 route add

【记录】路由表修改器

原本尝试直接使用api修改路由表 但由于对路由表项这一结构体部分参数不熟悉 导致调用api时 出现传入参数有误的情况 所以添加路由表还是用cmd 的route命令 /k /c cmd中表示 执行后不自动退出与自动退出 修改路由表的API 包含头 #include <windows.h>#include <Iphlpapi.h>#include <Ws2tcpip.h> #pragma comment(lib, "Iphlpapi.lib")#prag

Windows路由表

对于路由器的路由表,网管都很熟悉,但是windows的路由表,可能了解的人就相对少一些.今天我们就一起来看看windows路由表. 一.windows路由表 1.使用命令 route print 查看路由表信息 2.路由名称解释 Interface List: 列出了计算机上的网卡列表信息 Active Routes: 活动路由信息 Network Destination: 目的地网段 Netmask: 子网掩码,与目的网段共同指定了网络地址范围 Gateway: 网关,又称下一跳路由器 Int

路由表填充及准则

如果同一路由器从动态路由协议.手工配置的静态路由以及其他各种方式提供的路由中,有多条路径可达时,路由器选择前往目的地的最佳路径并放入路由表时将遵守如下准则: 有效的下一跳IP地址(Available Next Hop) 度量值(Metric) 管理距离(AD) 路由前缀(Prefix) 下面对上面4个原则进行详解: 有效的下一跳IP地址:路由进程收到更新和其他信息后,路由器首先检查路由的下一跳IP地址是否有效.这个还是比较好理解的,如果连"邻居"都不通,那么路由肯定不会选择原来的路径去