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;
}


發佈了417 篇原創文章 · 獲贊 21 · 訪問量 82萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章