UVa 12299 RMQ with shifts(线段树单点修改 区间查询)

由于命令长度最大才30,shift操作包含位置的数量不超过12,可以视为常数。

把每一个shift操作当成N个单点修改即可。

对命令字符串解析,使用:

for(int j=0;j<len;j++){
    if(isdigit(s[j])){
     sscanf(&s[j],"%d",&pos[p++]);
    }
    while(isdigit(s[j])){
     j++;
    }
   }

比较方便。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <algorithm>
#define maxn 100005
int a[maxn<<2];
int n[maxn];
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define INF 10000000
void pushup(int rt){
	int lc=rt<<1,rc=rt<<1|1;
	a[rt]=min(a[lc],a[rc]);
}

void build(int rt,int l,int r){
	if(l==r){
		a[rt]=n[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(rt);
}

void update(int rt,int l,int r,int pos,int num){
	if(l==r){
		a[rt]=num;
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=pos) update(lson,pos,num);
	else update(rson,pos,num);
	pushup(rt);
}

int Query(int rt,int l,int r,int L,int R){
	if(l>=L&&r<=R){
		return a[rt];
	}
	int mid=(l+r)>>1;
	int res=INF;
	if(mid>=L) res=min(res,Query(lson,L,R));
	if(mid<R) res=min(res,Query(rson,L,R));
	return res;
}
int N,Q;
int main(){
	scanf("%d%d",&N,&Q);
	for(int i=1;i<=N;i++){
		scanf("%d",&n[i]);
	}
	build(1,1,N);
	for(int i=1;i<=Q;i++){
		char s[40];
		scanf("%s",s);
		if(s[0]=='q'){
			int pos[2];
			int p=0;
			int len=strlen(s);
			for(int j=0;j<len;j++){
				if(isdigit(s[j])){
					sscanf(&s[j],"%d",&pos[p++]);
				}
				while(isdigit(s[j])){
					j++;
				}
			}
			printf("%d\n",Query(1,1,N,pos[0],pos[1]));
		}
		else{
			int pos[30];
			int p=0;
			int len=strlen(s);
			for(int j=0;j<len;j++){
				if(isdigit(s[j])){
					sscanf(&s[j],"%d",&pos[p++]);
				}
				while(isdigit(s[j])){
					j++;
				}
			}
			for(int k=0;k<p;k++){
				int next=(k+1)%p;
				update(1,1,N,pos[k],n[pos[next]]);
			}
			int tmp=n[pos[0]];
			for(int j=0;j<p-1;j++){
				n[pos[j]]=n[pos[j+1]];
			}
			n[pos[p-1]]=tmp;
		}
	}
	return 0;
}
/*
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);
*/



你可能感兴趣的:(线段树)