poj 4090:超级备忘录

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个大循环

length = 6 ; m = 2; length % m = 0; 共有m个大循环




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


代码

#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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值