zoukankan      html  css  js  c++  java
  • hdu 3333 Turing Tree(线段树+离散化)

    刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望。

    刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的。

    前两天我在做一道题的时候,也是因为数据范围太大(同样是1000000000)不能打表,当时想了许久,想到把这些数值存进一个数组里面,对这个数组进行排序,然后对于其中的某个值可以进行二分查找。今天我又长姿势了,原来这种方法叫做离散化。

    刚开始我想着可以把那些相同的值用0去替代,但是一个解决不了的问题是如果把两个相同的值其中一个改为0,那么如果问题区间刚好包含这个值不包含另一个值该怎么处理,甚至如果问题区间问的就是这个值,那该怎么办。

    苦思良久也没想到什么好办法。看了下别人的思路,是将所有的问题区间放在一起,以区间的右边界为关键字进行排序,然后对于线段树的值边插入边更新,具体思路见代码。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define N 100005
    #define M 30005
    struct node
    {
    	int x,y;
    	int id;
    }Q[N];
    struct tree
    {
    	int x,y;
    	__int64 sum;
    }a[M*3];
    int cmp(const void *a,const void *b)
    {
    	return *(int *)a-*(int *)b;
    }
    int cmp1(const void *a,const void *b)
    {
    	node *c;
    	node *d;
    	c=(node *)a;
    	d=(node *)b;
    	return c->y-d->y;
    }
    int visit[M],temp[M],tem[M],b[M];
    __int64 ans[N];
    void CreatTree(int t,int x,int y)
    {
    	a[t].x=x;
    	a[t].y=y;
    	a[t].sum=0;
    	if(x==y)
    		return ;
    	int temp=t*2;
    	int mid=(x+y)/2;
    	CreatTree(temp,x,mid);
    	CreatTree(temp+1,mid+1,y);
    	return ;
    }
    void InsertTree(int t,int x,int y)
    {
    	if(a[t].x==a[t].y)
    	{
    		a[t].sum+=y;
    		return ;
    	}
    	int temp=t*2;
    	int mid=(a[t].x+a[t].y)/2;
    	if(x<=mid)
    		InsertTree(temp,x,y);
    	else
    		InsertTree(temp+1,x,y);
    	a[t].sum=a[temp].sum+a[temp+1].sum;
    	return ;
    }
    __int64 FindTree(int t,int x,int y)
    {
    	if(a[t].x==x&&a[t].y==y)
    		return a[t].sum;
    	int temp=t*2;
    	int mid=(a[t].x+a[t].y)/2;
    	__int64 sum;
    	sum=0;
    	if(y<=mid)
    		sum+=FindTree(temp,x,y);
    	else if(x>mid)
    		sum+=FindTree(temp+1,x,y);
    	else
    	{
    		sum+=FindTree(temp,x,mid);
    		sum+=FindTree(temp+1,mid+1,y);
    	}
    	return sum;
    }
    int Find(int x,int k)
    {
    	int l,r,mid;
    	l=1;
    	r=k;
    	while(l<=r)
    	{
    		mid=(l+r)/2;
    		if(temp[mid]>x)
    			r=mid-1;
    		else if(temp[mid]<x)
    			l=mid+1;
    		else
    			return mid;
    	}
    	return 0;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		int n;
    		scanf("%d",&n);
    		CreatTree(1,1,n);
    		int i,j,k;
    		j=0;
    		for(i=1;i<=n;i++)
    		{
    			scanf("%d",&b[i]);
    			tem[j++]=b[i];
    		}
    		qsort(tem,j,sizeof(tem[0]),cmp);
    		k=0;
    		temp[0]=tem[0];
    		for(i=1;i<j;i++)
    		{
    			if(tem[i]!=temp[k])
    			{
    				k++;
    				temp[k]=tem[i];
    			}
    		}
    		memset(visit,0,sizeof(visit));
    		int m;
    		scanf("%d",&m);
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d",&Q[i].x,&Q[i].y);
    			Q[i].id=i;
    		}
    		qsort(Q+1,m,sizeof(Q[0]),cmp1);
    		j=1;
    		for(i=1;i<=n;i++)
    		{
    			int flag;
    			int id;
    			id=Find(b[i],k);
    			flag=visit[id];
    			if(flag)
    				InsertTree(1,flag,-b[i]);
    			InsertTree(1,i,b[i]);
    			visit[id]=i;
    			for(;j<=m;j++)
    			{
    				if(i==Q[j].y)
    				{
    					__int64 tt;
    					tt=FindTree(1,Q[j].x,Q[j].y);
    					ans[Q[j].id]=tt;
    				}
    				else
    					break;
    			}
    		}
    		for(i=1;i<=m;i++)
    			printf("%I64d
    ",ans[i]);
    	}
    	return 0;
    }
    


  • 相关阅读:
    Windows 编程,程序编译使用的命令行工具。
    showmemory.c 和 hello.s 源码
    jps命令
    A亚马逊WS网上系列讲座——怎么样AWS云平台上千万用户的应用建设
    Android比较字符串是空的(isEmpty)
    NSDictionary、NSMutableDictionary基本使用
    写贤治学生:关键是要管理好自己的时间
    Spark SQL Catalyst源代码分析Optimizer
    leetcode
    SQL Server 权限管理
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3190372.html
Copyright © 2011-2022 走看看