UVA-12299 RMQ with Shift(線分樹)

2237 ワード

テーマリンク:https://vjudge.net/problem/UVA-12299
考え:裸の線分樹は、移動時に最大30個を超えないので、直接に注文して更新すればいいです.その後、区間で調べてみます.答えの間には空行があります.
#include 
#define lson num << 1
#define rson num << 1 | 1
#define MAXN 100005
using namespace std;
struct node
{
	int l,r;
	int Min;
}tree[MAXN << 2];
int a[MAXN],val[MAXN];
void pushup(int num)
{
	tree[num].Min = min(tree[lson].Min,tree[rson].Min);
}
void build(int num,int l,int r)
{
	tree[num].l = l;
	tree[num].r = r;
	if(l == r) {
		tree[num].Min = a[l];
		return;
	}
	int mid = (tree[num].l + tree[num].r) >> 1;
	build(lson,l,mid);
	build(rson,mid + 1,r);
	pushup(num);
}
int query(int num,int l,int r) 
{
	if(tree[num].l == l && tree[num].r == r) {
		return tree[num].Min;
	}
	int mid = (tree[num].l + tree[num].r) >> 1;
	if(r <= mid) return query(lson,l,r);
	else if(l > mid) return query(rson,l,r);
	else return min(query(lson,l,mid),query(rson,mid + 1,r));
}
void update(int num,int pos)
{
	if(tree[num].l == pos && tree[num].r == pos) {
		tree[num].Min = a[pos];
		return;
	}
	int mid = (tree[num].l + tree[num].r) >> 1;
	if(pos <= mid) update(lson,pos);
	else update(rson,pos);
	pushup(num);
}
int main(void)
{
	int n,q,len,l,r,i,j;
	char op[50];
	int pos[50],cnt,end;
	scanf("%d %d",&n,&q);
	for(i = 1; i <= n; i++) {
		scanf("%d",&a[i]);
	}
	build(1,1,n);
	while(q--) {
		scanf("%s",op);
		len = strlen(op);
		if(op[0] == 'q') {
			l = 0,r = 0;
			for(i = 6; i < len; i++) {
				if(op[i] == ',') break;
				l = l * 10 + op[i] - '0';
			}
			for(j = i + 1; j < len - 1; j++) {
				r = r * 10 + op[j] - '0';
			}
			printf("%d
",query(1,l,r)); } else { cnt = 0; memset(pos,0,sizeof(pos)); for(i = 6; i < len - 1; i++) { if(op[i] == ',') cnt++; else pos[cnt] = pos[cnt] * 10 + op[i] - '0'; } for(i = 0; i <= cnt; i++) { val[pos[i]] = a[pos[i]]; } for(int i = 0; i <= cnt; i++) { a[pos[i]] = val[pos[(i + 1) % (cnt + 1)]]; update(1,pos[i]); } } } 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) */