`

【线段树+离散化+离线方法】杭电 hdu 3333 Turing Tree

阅读更多

 

/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
    Copyright (c) 2012 panyanyany All rights reserved.

    URL   : http://acm.hdu.edu.cn/showproblem.php?pid=3333
    Name  : 3333 Turing Tree

    Date  : Friday, April 20, 2012
    Time Stage : 2 hours

    Result:
5812358	2012-04-20 20:19:31	Accepted	3333
515MS	3480K	3538 B
C++	pyy								

Test Data :

Review :
离线方法+线段树+离散化
参考了大牛的文章,才AC的
http://www.cnblogs.com/staginner/archive/2012/04/13/2445104.html
我只是做了些注释……
没有想到MAXQ开小了也会TLE
//----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>

#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <string>

using namespace std ;

#define MEM(a, v)        memset (a, v, sizeof (a))    // a for address, v for value
#define max(x, y)        ((x) > (y) ? (x) : (y))
#define min(x, y)        ((x) < (y) ? (x) : (y))

#define INF     (0x3f3f3f3f)
#define MAXN	30009
#define MAXQ	100010

#define L(x)	((x)<<1)
#define R(x)	(((x)<<1)|1)

#define DB    /##/
typedef __int64	LL;

struct NODE {
	int x, y;
	LL  sum;
};

int		tcase, n, q, iDis;	// iDis 表示 iDiscrete 
int		src[MAXN], ssrc[MAXN], idques[MAXQ], idseg[MAXN];
LL		sum[MAXN*4];

NODE	question[MAXQ];

bool cmp(const int &i, const int &j)
{
	return question[i].y < question[j].y;
}

int rank(int val)
{
	int mid, lw = 0, up = iDis;
	while (lw <= up)
	{
		mid = (lw + up) >> 1;
		if (ssrc[mid] == val)
			break;

		if (val < ssrc[mid])
			up = mid - 1;
		else
			lw = mid + 1;
	}
	return mid;
}

inline void build()
{
	MEM(sum, 0);
}

void update(int id, int lf, int rh, int pos, int f)
{
	if (lf == rh)
	{
		sum[id] = f ? src[pos] : 0;	// 不是 sum[lf] 或 sum[pos]
		return ;
	}

	int mid = (lf + rh) >> 1;
	if (pos <= mid)
		update(L(id), lf, mid, pos, f);
	else
		update(R(id), mid+1, rh, pos, f);

	sum[id] = sum[L(id)] + sum[R(id)];
}

LL query(int id, int lf, int rh, int s, int t)
{
	if (s == lf && t == rh)
		return sum[id];
	
	int mid = (lf + rh) >> 1;
	if (t <= mid)
		return query(L(id), lf, mid, s, t);
	else if (mid < s)
		return query(R(id), mid+1, rh, s, t);

	return query(L(id), lf, mid, s, mid) + query(R(id), mid+1, rh, mid+1, t);
}

int main()
{
	int i, j, k;
	while (scanf("%d", &tcase) != EOF)
	{
		while (tcase--)
		{
			scanf("%d", &n);
			for (i = 0; i < n; ++i)
			{
				scanf("%d", src+i);
				ssrc[i] = src[i];	// ssrc 表示被排序过的src 即 sorted src
			}
			// 离散化
			sort(ssrc, ssrc+n);
			for (i = iDis = 1; i < n; ++i)
			{
				if (ssrc[iDis-1] != ssrc[i])
					ssrc[iDis++] = ssrc[i];
			} // 离散化完

			scanf("%d", &q);
			for (i = 0; i < q; ++i)
			{
				scanf("%d %d", &question[i].x, &question[i].y);
				--question[i].x; --question[i].y;
				idques[i] = i;
			}

			// 对 question 的下标进行排序,相当于间接排序了 question 数组
			sort(idques, idques+q, cmp);

			MEM(idseg, -1);

			// build
			build();
			for (i = j = 0; i < n; ++i)
			{
				k = rank(src[i]);
				if (-1 != idseg[k])
					// 到上一次 src[i] 出现的位置(idseg[k]),将 src[i] 删除.
					update(1, 0, n-1, idseg[k], 0);
				idseg[k] = i;	// 记录此次 src[i] 出现的位置
				update(1, 0, n-1, i, 1);// 将 src[i] 加入线段树中

				// 对排序过的查询区间进行处理
				while (j < q && question[idques[j]].y == i)
				{
					question[idques[j]].sum = query(1, 0, n-1,
						question[idques[j]].x, i);
					++j;
				}
			}

			// 按原顺序输出结果
			for (i = 0; i < q; ++i)
				printf ("%I64d\n", question[i].sum);
		}
	}
	return 0;
}
 
0
1
分享到:
评论

相关推荐

    hdu 3333 turing tree 解题报告

    题目“HDU 3333 Turing Tree”要求解决的问题是:给定一个整数序列和一系列区间,计算每个区间内不重复数字的和。由于数据规模较大(N ,000, K ,000),直接的暴力方法效率过低,因此我们需要采用一种更高效的数据...

    杭电HDU ACM培训课件

    《杭电HDU ACM培训课件》是一份珍贵的学习资源,源自杭州电子科技大学的ACM竞赛培训课程。这些课件是官方论坛上分享的,旨在为那些积分不足无法获取资源或者对ACM编程竞赛感兴趣的初学者提供帮助。下面将详细阐述这...

    杭电OJ离线版

    杭州电子科技大学 oj离线版

    ACM hdu 线段树题目+源代码

    ACM hdu 线段树题目+源代码 线段树是一种非常重要的数据结构,它广泛应用于算法竞赛和实际编程中。今天,我们将通过 ACM hdu 的几个题目来学习和掌握线段树的基本概念和应用。 线段树的基本概念 线段树是一种...

    杭电HDU2050题的ac程序

    一个十分简单的程序,能够ac杭电hdu的第2050题,无注释,简单明了

    计算机网络复习大纲_杭电hdu.pdf

    计算机网络复习大纲_杭电hdu.pdf

    计算机网络复习大纲_杭电hdu整理.pdf

    计算机网络复习大纲_杭电hdu整理.pdf

    计算机网络复习大纲_杭电hdu参考.pdf

    计算机网络复习大纲_杭电hdu参考.pdf

    杭电HDU ACM 1005

    杭电ACM1005题源代码,AC了的程序,无问题……

    杭电操作系统实验 HDU操作系统实验.zip

    杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU操作系统实验.zip杭电操作系统实验 HDU...

    离线OJ题库(HDU ZJU等,部分有答案)

    离线OJ题库是为编程爱好者和程序员提供的一种便捷的学习资源,主要包含来自不同在线判题系统(如HDU - 浙江大学多模式在线评测系统,ZJU - 浙江大学在线评测系统等)的编程题目。这类题库通常包含多种编程语言的题目...

    hdu 1166线段树

    标题与描述均提到了“hdu 1166线段树”,这表明文章的核心是关于线段树在解决特定问题中的应用。线段树是一种数据结构,主要用于处理区间查询和更新操作,尤其是在大规模数据集上。在本例中,通过分析给定的部分代码...

    杭电ACMhdu1163

    【标题】:杭电ACMhdu1163 【描述】:这是一道源自杭州电子科技大学(Hangzhou Dianzi University,简称HDU)的ACM编程竞赛题目,编号为1163。这类问题通常需要参赛者利用计算机编程解决数学、逻辑或算法上的挑战,...

    hdu acm1166线段树

    hdu 1166线段树代码

    杭电(HDU) OJ离线版

    为了方便广大没有网络的朋友.......

    线段树完整版

    ### 线段树知识点详解 #### 一、线段树基本概念与应用 线段树是一种二叉树数据结构,常用于处理区间查询或区间更新的问题。它将一个线性序列分割成多个不连续的段,每一个节点代表一个区间,并且通过递归的方式将...

    线段树入门学习(兼解HDU1754)

    线段树可以很好地解决这类问题,通过一次预处理构建线段树,后续的修改和查询操作都能在较短的时间复杂度内完成,比直接遍历数组的方法高效得多。 在“Main.java”文件中,我们可以预期看到线段树的实现代码。代码...

Global site tag (gtag.js) - Google Analytics