【BZOJ4523】【CQOI2016】路由表 Trie

【BZOJ4523】【CQOI2016】路由表 Trie_第1张图片【BZOJ4523】【CQOI2016】路由表 Trie_第2张图片

数据保证无相同有效地址(地址中掩码部分)出现

对于一次查询的一种理解方式是:无视其它所有查询操作,只看添加操作。先清空路由表,然后执行第1到a-1次添加操作。之后再执行第a到b次添加操作过程中,统计匹配改变的次数。

第一眼扫过去是可持久,<del>但是转念一想去年CQOI考过这东西果断跳过<del>

<del>这题对拍数据之难做hhh<del>

这年头输入都不按套路来。。。间接考察了一波输入优化

思路比较清晰,插入的地址的有效部分甩进一棵Trie,末尾节点的值标记为插入时间,不难想到搜索时改变匹配项的条件是:沿着trie一路找下去,出现插入时间更靠后的项。

因此我们在沿着trie查找时维护一个栈,无视时间大于B的操作,保证栈内的插入时间递增,找完之后在定位小于a的最后一项。栈内大于a的元素个数就是改变的次数。

(这题开100000*40的数组就能A这种事我是不会说的)

#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define maxn 1000005
int np,rt,chi[maxn*35][2],val[maxn*35];
int n,L;
int s[40];
void _read(int &x)
{
	x=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0' && ch<='9')
	{
		x=x*10+ch-'0'; ch=getchar();
	}
	return ;
}
void getIP()
{
	int cnt=0,x;
	for(int i=1;i<=4;i++)
	{
		_read(x);
		for(int j=7;j>=0;j--)
		{
			s[++cnt]=(1&(x>>j));
		}
	}
	return ;
}
void Insert(int time)
{
	int now=rt,d;
	for(int i=1;i<=L;i++)
	{
		d=s[i];
		if(!chi[now][d])
		{
			chi[now][d]=++np;chi[np][0]=chi[np][1]=0;val[np]=0;
		}
		now=chi[now][d];
	}
	val[now]=time;
	return ;
}
int st[40],top;
void query(int a,int b)
{
	top=0;
	int d,t,now=rt;
	for(int i=1;i<=32;i++)
	{
		d=s[i];
		if(!chi[now][d])break;
		now=chi[now][d];
		if(val[now])
		{
			t=val[now];
			if(t>b)continue;
			while(top>0 && st[top]>t)
			{
				top--;
			}
			st[++top]=t;
		}
	}
	int c=0;
	while(c<top && st[c+1]<a)c++;
	printf("%d\n",top-c);
	return ;
}
void work()
{
	int cnt=0,x,y;
	char op;
	np=rt=1;chi[0][0]=chi[1][0]=chi[0][1]=chi[1][1]=0;
	val[0]=val[1]=0;
	scanf("%d",&n);
	int woc=0;
	for(int i=1;i<=n;i++)
	{
		op=getchar();
		while(op!='A' && op!='Q')
		{
			op=getchar();
		}
		if(op=='A')
		{
			cnt++;
			getIP();_read(L);
			Insert(cnt);
		}
		else
		{
			woc++;
			getIP();_read(x); _read(y);
			query(x,y);
		}
		//cout<<i<<endl;
	}
	return ;
}
int main()
{
	//freopen("route.in","r",stdin);
	//freopen("route.out","w",stdout);
	
	work();
	return 0;
}


你可能感兴趣的:(【BZOJ4523】【CQOI2016】路由表 Trie)