UVA12299--线段树

本文介绍了一种解决区间查询与数组更新问题的算法实现,包括构建线段树、更新节点值及查询区间最小值的方法。通过对具体示例的解析,展示了如何高效地处理数组的查询与更新操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R) (L$ \le$R), we report the minimum value among A[L], A[L + 1], ..., A[R]. Note that the indices start from 1, i.e. the left-most element is A[1].

In this problem, the array A is no longer static: we need to support another operation

shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields 8, 6, 4, 5, 4, 1, 2.

Input

There will be only one test case, beginning with two integers n, q (1$ \le$n$ \le$100, 000, 1$ \le$q$ \le$250, 000), the number of integers in array A, and the number of operations. The next line contains n positive integers not greater than 100,000, the initial elements in array A. Each of the next q lines contains an operation. Each operation is formatted as a string having no more than 30 characters, with no space characters inside. All operations are guaranteed to be valid.


Warning: The dataset is large, better to use faster I/O methods.

Output

For each query, print the minimum value (rather than index) in the requested range.

Sample Input

7 5
6 2 4 8 5 1 4
query(3,7)
shift(2,4,5,7)
query(1,4)
shift(1,2)
query(2,2)

Sample Output

1
4
6
思路:卡题久了切切水题找手感~~单点修改,区间查询。直接一个一个update就行了、、
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100080
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
int key[maxn],know[maxn];
char str[38];
int sft[20];
struct ST
{
	int l,r,minkey;
}st[maxn<<2];

inline int min(int a,int b)
{
	return a>b?b:a;
}

void PushUp(int id)
{
	st[id].minkey = min(st[id<<1].minkey,st[id<<1|1].minkey);
}

void Update(int id,int pos,int k)
{
	if(st[id].l == pos && st[id].r == pos)
	{
		st[id].minkey = k;
		return;
	}
	if(st[id<<1].r >= pos)
		Update(id<<1,pos,k);
	else Update(id<<1|1,pos,k);
	PushUp(id);
}

void buildtree(int id,int l,int r)
{
	st[id].l = l ,st[id].r = r;
	if(l == r)
	{
		st[id].minkey = key[l];
		return;
	}
	int mid = (l+r) >> 1;
	buildtree(lson);
	buildtree(rson);
	PushUp(id);
}

int query(int id,int l,int r)
{
	if(st[id].l == l && st[id].r == r)
		return st[id].minkey;
	if(st[id<<1].r >= r)
		return query(id<<1,l,r);
	else if(st[id<<1|1].l <= l)
		return query(id<<1|1,l,r);
	else return min(query(id<<1,l,st[id<<1].r),query(id<<1|1,st[id<<1|1].l,r));
}

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)==2)
	{
		for(int i = 1;i <= n;i++)	scanf("%d",&key[i]);
		buildtree(1,1,n);
		while(m--)
		{
			getchar();//吃回车
			char c = getchar();
			for(int i = 1;i <= 5;i++)	getchar();
			if(c == 'q')
			{
				int u,v;
				scanf("%d,%d)",&u,&v);
				printf("%d\n",query(1,u,v));
			}
			else
			{
				int pos = 0;
				while(1)
				{
					scanf("%d",&sft[pos++]);
					if(getchar() == ')')	break;
				}
				for(int i = 0;i < pos;i++)
				{
					if(i == pos-1)
					{
						Update(1,sft[i],key[sft[0]]);
						know[sft[i]] = key[sft[0]];
					}
					else 
					{
						Update(1,sft[i],key[sft[i+1]]);
						know[sft[i]] = key[sft[i+1]];
					}
				}
				for(int i = 0;i < pos;i++)
					key[sft[i]] = know[sft[i]];
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值