UVA 12299


线段树:n个数a[n],m个操作;

query(a,b):求a到b区间的最小值;

shift(……):shift里的数代表数组a的下标,把给定的下标的数向左移一位;

如:

7 5
6 2 4 8 5 1 4

shift(2,4,5,7)
对应的数(2 8 5 4)

则数组变为:6 8 4 5 4 1 2;







#include <stdio.h>
#include <string.h>
#include <math.h>
#include <string>
#define INF 999999999

int min[100005*4],Ad[100005];
int cont;

int Min(int a,int b)
{
	if(a<b)
		return a;
	else
		return b;
}

void build(int l,int r,int rt)
{
	if(l==r)
	{
		min[rt]=Ad[l];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,rt*2);
	build(mid+1,r,rt*2+1);
	min[rt]=Min(min[rt*2],min[rt*2+1]);
}

int query(int l,int r,int L,int R,int rt)
{
	if(l<=L && r>=R)
		return min[rt];
	int mid=(L+R)/2;
	int ans=INF;
	if(l<=mid)
		ans=Min(ans,query(l,r,L,mid,rt*2));
	if(r>mid)
		ans=Min(ans,query(l,r,mid+1,R,rt*2+1));
	return ans;
}

void update(int l,int r,int rt,int u,int v)
{
	if(l==r)
	{
		min[rt]=v;
		return;
	}
	int mid=(l+r)/2;
	if(u<=mid)
		update(l,mid,rt*2,u,v);
	else
		update(mid+1,r,rt*2+1,u,v);
	min[rt]=Min(min[rt*2],min[rt*2+1]);
}

int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=1;i<=n;i++)
			scanf("%d",&Ad[i]);
		build(1,n,1);
		while(m--)
		{
			char ch[50];
			scanf("%s",ch);
			if(ch[0]=='q')
			{
				int a,b;
				sscanf(ch+6,"%d,%d",&a,&b);
				printf("%d\n",query(a,b,1,n,1));
			}
			else
			{
				int a[100];
				int k=0;
				for(int i=6;ch[i]!='\n';)
				{
					int x=0;
					int j=i;
					while(ch[j]!=',' && ch[j]!=')')
					{
						x=x*10+ch[j]-'0';
						j++;
					}
					a[++k]=x;

					if(ch[j]==')')
						break;
					else
						i=j+1;
				}
				int p=query(a[1],a[1],1,n,1);//找出下标为a[1]的数 p
				for(int i=1;i<k;i++)
				{
					int temp=query(a[i+1],a[i+1],1,n,1);//找出下标为a[i+1] 的数 temp
					update(1,n,1,a[i],temp);//更新下标 a[i] 的数为 下标a[i+1]的数
				}
				update(1,n,1,a[k],p);//更新最后一位
			}
		}
	}
	return 0;
}


你可能感兴趣的:(UVA 12299)