hdu 3333 Turing Tree(图灵树)

很不错的一道线段树题目,做了两天,终于给弄明白了。。。

看别人blog的时候,发现总是说离散化,,不明白什么意思。。。上网搜了下,其实就是一种思想的转化,,有时候我们一直在用,只不过不知道叫什么名字罢了。。。

比如对于这道题, 我们如果讨论一个数,判断它前面是否出现过,,因为0 ≤ Ai ≤ 1,000,000,000 ,很显然我们不能直接 用一个visit去判断。。

但是由于1 ≤ N ≤ 30,000 ,我们可以开一个30000的数组,然后把这些数存起来,排好序, 之后再判断一个数是否出现过的时候, 就可以用二分找到它的下标。。

对下表进行visit记录就可以了。。。

题意:  给出一个长度为N(N <= 30000)的数列,然后是一连串询问,询问数<= 100000,问给定区间内不同数字的和。

因为数字的范围较大,所以首先是对数列进行离散化,一般可以用二分或者hash,将大范围的数字映射到连续的区间。

然后一次性读入所有的区间(整数对),并且对整数对的右端点进行递增排序。这里注意,要记录下整数对读入的位置下标。。。

接下来按顺序枚举每个数字a[i],如果a[i]之前出现过,就将a[i]之前位置的值删除,然后在当前位置插入,当枚举的位置和区间对中某个位置相
等时执行询问操作。。。。
代码:

# include<stdio.h>

# include<string.h>

# include<stdlib.h>

# define N 30005

# define M 100005

struct node{

	int from,to,idx;

}Q[M];



struct node1{

	int left,right;

	__int64 num;

}tree[N*4];

int a[N],tem[N],visit[N],temp[N],k;

__int64 ans1,ans[M];



int cmp(const void *a,const void *b)

{

	struct node *c=(struct node *)a;

	struct node *d=(struct node *)b;

	return c->to - d->to;

}

int cmp1(const void *a,const void *b)

{

	return *(int *)a - *(int *)b;

}

void bulid(int l,int r,int t)

{

	int mid;

	tree[t].num=0;

	tree[t].left=l;

	tree[t].right=r;

	if(l==r) return;

	mid=(l+r)/2;

	bulid(l,mid,2*t);

	bulid(mid+1,r,2*t+1);

}

void insert(int t,int p,int val)

{

	int mid;

	if(tree[t].left==tree[t].right) {tree[t].num+=val;return;}

	mid=(tree[t].left+tree[t].right)/2;

	if(p<=mid) insert(2*t,p,val);

	else if(p>mid) insert(2*t+1,p,val);

	tree[t].num=tree[2*t].num+tree[2*t+1].num;

}

void Query(int t,int l,int r)

{

	int mid;

	if(tree[t].left==l && tree[t].right==r) 

	{

		ans1+=tree[t].num;return;

	}

	mid=(tree[t].left+tree[t].right)/2;

	if(r<=mid) Query(2*t,l,r);

	else if(l>mid) Query(2*t+1,l,r);

	else

	{

		Query(2*t,l,mid);

		Query(2*t+1,mid+1,r

			);

	}

}

int is(int v)

{

	int l,r,mid;

	l=1;r=k;

	while(l<=r)

	{

		mid=(l+r)/2;

		if(temp[mid]>v) r=mid-1;

		else if(v>temp[mid]) l=mid+1;

		else return mid;

	}

}

int main()

{

	int i,j,n,ncase,id,flag,t,m;

	scanf("%d",&ncase);

	while(ncase--)

	{

		scanf("%d",&n);

		t=0;

		for(i=1;i<=n;i++)

		{

			scanf("%d",&a[i]);

			tem[t++]=a[i];

		}

		qsort(tem,t,sizeof(tem[0]),cmp1);

		temp[1]=tem[0];

		k=1;

		for(i=1;i<t;i++)

		{

			if(tem[i]!=tem[i-1]) 

			{

				k++;

				temp[k]=tem[i];

			}

		}

		memset(visit,0,sizeof(visit));

		scanf("%d",&m);

		for(i=1;i<=m;i++)

		{

			scanf("%d%d",&Q[i].from,&Q[i].to);

			Q[i].idx=i;

		}

		qsort(Q+1,m,sizeof(Q[1]),cmp);

			bulid(1,n,1);

		j=1;

		for(i=1;i<=n;i++)

		{

			id=is(a[i]);

			flag=visit[id];

			if(flag)

			{

				insert(1,flag,-a[i]);

			}

			insert(1,i,a[i]);

			visit[id]=i;

			for(;j<=m;j++)

			{

				if(i==Q[j].to)

				{

					ans1=0;

					Query(1,Q[j].from,Q[j].to);

					ans[Q[j].idx]=ans1;

				}

				else break;

			}

		}

		for(i=1;i<=m;i++)

		{

			printf("%I64d\n",ans[i]);

		}

	}

	return 0;

}

你可能感兴趣的:(tree)