POJ 1207 解题报告

最近用了好几次线段树,所以这道题还是用线段树做的。首先,用DFS(其实也算DP)算出来1~10000之间的所有数的“cycle length”,没到1之前前一个数的cycle length等于后一个数的cycle length加1。然后可以建立一个线段树。查询是一个在线段树上做范围查询的过程。

很喜欢线段树这个数据结构。

1207Accepted412K0MSC++2028B

/* 
ID: thestor1 
LANG: C++ 
TASK: poj1207 
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

const int MAXN = 10000;

int DFS(int num, int length[])
{
	if (num <= MAXN && length[num] > 0)
	{
		return length[num];
	}

	if (num == 1)
	{
		length[num] = 1;
		return 1;
	}
	else
	{
		int next = num & 1 ? 3 * num + 1 : num / 2;
		int len = DFS(next, length) + 1;

		if (num < MAXN)
		{
			length[num] = len;
		}

		return len;
	}
}

int buildSegmentTree(std::vector<int> &segmentTree, int left, int right, int index, int length[])
{
	if (left == right)
	{
		segmentTree[index] = length[left];
		return segmentTree[index];
	}

	int mid = left + ((right - left) >> 1);
	segmentTree[index] = max(buildSegmentTree(segmentTree, left, mid, 2 * index + 1, length), buildSegmentTree(segmentTree, mid + 1, right, 2 * index + 2, length));
	return segmentTree[index];
}

int queryMax(std::vector<int> &segmentTree, int left, int right, int index, const int lindex, const int rindex)
{
	if (rindex < left || right < lindex)
	{
		return 0;
	}

	if (lindex <= left && right <= rindex)
	{
		return segmentTree[index];
	}

	int mid = left + ((right - left) >> 1);
	return max(queryMax(segmentTree, left, mid, 2 * index + 1, lindex, rindex), queryMax(segmentTree, mid + 1, right, 2 * index + 2, lindex, rindex));
}

int main()
{
	int length[MAXN + 1] = {0};
	for (int i = 1; i <= MAXN; ++i)
	{
		if (length[i] == 0)
		{
			DFS(i, length);
		}
	}

	std::vector<int> segmentTree(4 * (MAXN + 1), 0);
	buildSegmentTree(segmentTree, 0, MAXN, 0, length);

	int i, j;
	while (cin >> i >> j)
	{
		cout << i << " " << j << " " << queryMax(segmentTree, 0, MAXN, 0, min(i, j), max(i, j)) << endl;
	}

	return 0;  
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值