码迷,mamicode.com
首页 > 其他好文 > 详细

HDOJ 5269///Trie

时间:2015-08-21 13:51:25      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:trie   hdoj   

附 Bestcoeder 上的题解原文


我们考虑,当A的答案为2^p时,A和B表示成二进制数后末p-1位肯定相同 于是我们维护一颗字母树,将每个数表示成二进制数后翻转可以下,插入字母树 统计答案时,我们找出Ai的二进制数翻转后在字母树上的路径,对于路径上每个点x,设他走的边是v,且当前为第k位,则和他xor后lowbit为2^k的数的个数为trans(x,v^1)的子树大小。 trans(x,v)表示字母树上在结点x,走连出去的字母为v的边到达的结点 时间复杂度:O(nlogA)
O(nlogA)


。。。。。。蒟蒻想到要建树然而具体不知道。。。。。。

看题解用数组写了一遍TLE了 ⊙_⊙

。。。于是只能第一次用指针建树。。。


#include <iostream>
#include <cstdio>
#include <cstring>

struct tree
{
	int cnt;
	tree *ch[2];
	tree()
	{
		cnt=0;
		memset(ch,0,sizeof(ch));
	}
};
const int Mod=998244353;
const int N=50100;
int a[N];
int T,t,n;

void ins(tree *rt,int x)
{
	int i;
	for (i=0;i<30;i++)
	{
		int f=x&1;
		if (rt->ch[f]==NULL) rt->ch[f]=new tree();
		rt=rt->ch[f];
		rt->cnt++;
		x>>=1;
	}
}

long long cal(tree *rt,int x)
{
	int i;
	int res=0;
	for (i=0;i<30;i++)
	{
		int f=x&1;
		tree *op=rt->ch[f^1];
		if (op) res=(res+(op->cnt)*(1<<i))%Mod;
		rt=rt->ch[f];
		x>>=1;
	}
	return res;
}

int main()
{
	scanf("%d",&T);
	for (t=1;t<=T;t++)
	{
		tree *rt=new tree();
		scanf("%d",&n);
		int i;
		for (i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			ins(rt,a[i]);
		}
		long long ans=0;
		for (i=1;i<=n;i++)
			ans=(ans+cal(rt,a[i]))%Mod;
//		empty(rt)懒得写了 不过还是A了。。。 
		printf("Case #%d: %I64d\n",t,ans);
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDOJ 5269///Trie

标签:trie   hdoj   

原文地址:http://blog.csdn.net/summonlight/article/details/47830939

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!