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

poj 4090:超级备忘录

时间:2014-10-26 21:16:23      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:poj

poj 4090:超级备忘录


题目:
描述

你的朋友Jackson被邀请参加一个叫做“超级备忘录”的电视节目。在这个节目中,参与者需要玩一个记忆游戏。在一开始,主持人会告诉所有参与者一个数列,{A1, A2, ..., An}。接下来,主持人会在数列上做一些操作,操作包括以下几种:

  1. ADD x y D:给子序列{Ax, ..., Ay}统一加上一个数D。例如,在{1, 2, 3, 4, 5}上进行操作"ADD 2 4 1"会得到{1, 3, 4, 5, 5}。

  2. REVERSE x y:将子序列{Ax, ..., Ay}逆序排布。例如,在{1, 2, 3, 4, 5}上进行操作"REVERSE 2 4"会得到{1, 4, 3, 2, 5}。

  3. REVOLVE x y T:将子序列{Ax, ..., Ay}轮换T次。例如,在{1, 2, 3, 4, 5}上进行操作"REVOLVE 2 4 2"会得到{1, 3, 4, 2, 5}。

  4. INSERT x P:在Ax后面插入P。例如,在{1, 2, 3, 4, 5}上进行操作"INSERT 2 4"会得到{1, 2, 4, 3, 4, 5}。

  5. DELETE x:删除Ax。在Ax后面插入P。例如,在{1, 2, 3, 4, 5}上进行操作"DELETE 2"会得到{1, 3, 4, 5}。

  6. MIN x y:查询子序列{Ax, ..., Ay}中的最小值。例如,{1, 2, 3, 4, 5}上执行"MIN 2 4"的正确答案为2。

为了使得节目更加好看,每个参赛人都有机会在觉得困难时打电话请求场外观众的帮助。你的任务是看这个电视节目,然后写一个程序对于每一个询问计算出结果,这样可以使得Jackson在任何时候打电话求助你的时候,你都可以给出正确答案。

输入
第一行包含一个数n (n ≤ 100000)。
接下来n行给出了序列中的数。
接下来一行包含一个数M (M ≤ 100000),描述操作和询问的数量。
接下来M行给出了所有的操作和询问。
解题方案
这里面最有深度的题目就是旋转了,所以分析只有针对旋转的
对一个数组旋转怎么做呢?暴力法可以么,可以,但是很慢
那么我们怎么办?如果实验较多我们会发现有一个规律,我们设 length 为数组长度,需要旋转的次数为 n (0 < n < length )

我们将根据 length 是否能整除 m (= n<(length-n) ? n : length - n )分为两种情况设计算法
但是每一种情况时间复杂度都是 O(length),所以这是比较快的
我们先看能整除的那种情况

length = 6; m = 1; length % m = 0;共有m个大循环
bubuko.com,布布扣

length = 6 ; m = 2; length % m = 0; 共有m个大循环
bubuko.com,布布扣


bubuko.com,布布扣

第二种情况,不能整除
length = 7 ;n = 4 ; m = 3 ;length % m == 1; 这时只用一个大循环就可以。
bubuko.com,布布扣

代码

#include <iostream>
using namespace std;


class intList
{
	int * data;
	int length;
public:
	intList()
	{
		data = NULL;
		length = 0;
	}

	void add( int x,int y,int D )
	{
		for( int i=x;i<=y;i++ )
		{
			data[i-1] += D;
		}
	}

	void reverse( int x,int y )
	{
		for(int i = 0; i < (y-x+1)/2 ; i++)
		{
			int d = data[x+i-1];
			data[x+i-1] = data[y-i-1];
			data[y-i-1] = d;
		}
	}

	void revolve(int x,int y,int T)
	{
		int len = y - x + 1;
		int m = T<(len-T)? T:(len - T);
		T = T % len;
		if( T != 0 )
		if( len % m == 0 )
		{
			for(int i=0;i<m;i++)
			{
				int flag = i;
				int flag_data = data[i+x-1];
				int j = i ;
				while ( (j+T)%len != flag )
				{
					int d = data[(j+T)%len + x-1];
					data[(j+T)%len + x-1] = flag_data ;
					flag_data = d;
					j = (j+T)%len ;
				}
				data[flag+x-1] = flag_data;
			}
		}
		else
		{
			int flag = 0;
			int flag_data = data[flag+x-1];
			int j = 0;

			while( (j+T)%len != flag )
			{
				int d = data[(j+T)%len + x-1] ;
				data[(j+T)%len + x-1] = flag_data ;
				flag_data = d ;
				j = (j+T)%len ;
			}
			data[flag] = flag_data ;
		}
	}

	void insert( int x,int P )
	{
		length++ ;
		int * big_data = new int[ length ];

		for(int i=length-1;i>=x;i--)
			big_data[i] = data[i-1];
		big_data[x-1] = P;
		for(int i=x-2;i>=0;i--)
			big_data[i] = data[i];

		delete [] data;
		data = big_data;
	}

	void delete_x(int x)
	{
		for( int i = x-1;i < length-1 ; i++ )
		{
			data[i] = data[i+1];
		}
		length -- ;
	}

	int min(int x,int y)
	{
		int min = INT_MAX;
		for(int i=x; i<=y; i++)
		{
			if(data[i-1] < min )
				min = data[i-1];
		}
		return min;
	}

	void print_list()
	{
		for( int i=0; i<length; i++ )
		{
			cout<<data[i]<<" ";
		}
		cout<<endl;
	}
};



int main()
{
	intList mylist;

	for(int i=1;i<10;i++)
	mylist.insert(i,i);
	mylist.print_list();

	mylist.insert( 1,4 );
	mylist.add( 1,9,1 );
	mylist.print_list( );

	mylist.delete_x( 3 );
	mylist.print_list( );

	cout<<mylist.min(5,9)<<endl;

	mylist.revolve(1,6,4);
	mylist.print_list( );

	mylist.reverse(1,4);
	mylist.print_list();
	system("pause");
	return 0;
}


poj 4090:超级备忘录

标签:poj

原文地址:http://blog.csdn.net/cqs_experiment/article/details/40478391

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