题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3720
题意:给你一个可变的数组A,有两种操作。操作一:shift(i1, i2....in),将数组中这些元素的值变为(A[i2], A[i3]....A[in], A[i1]),操作二:Query(L, R),
查询A[i](L<=i <=R)的和。
题中 Each operation is formatted as a string having no more than 30 characters, 暗示每次参与shift操作的元素不多,所以直接可以使用单点更新的方式来解决问题。
#include <iostream> #include <cstring> #include <algorithm> #define maxn 100010 #define maxl 50 #define inf 1000000000 #define LL(x) x<<1 #define RR(x) x<<1|1 using namespace std; typedef long long LL; //variable define struct tree { int l, r; int mi; }; tree node[maxn<<2]; int n, m, arr[maxn], tmp[maxl], tot; //function define void push_up(int x); void build_tree(int left, int right, int x); int query(int left, int right, int x); void update(int left, int right, int x, int val); void solve(); bool is_number(char ch); int main(void) { while (scanf("%d %d", &n, &m) != EOF) { tot = 1; build_tree( 1, n, 1); solve(); } return 0; } void build_tree(int left, int right, int x) { node[x].l = left; node[x].r = right; if (left == right) { scanf("%d", &node[x].mi); arr[tot++] = node[x].mi; return; } int lx = LL(x); int rx = RR(x); int mid = left + (right - left)/2; build_tree(left, mid, lx); build_tree(mid + 1, right, rx); push_up(x); } void push_up(int x) { if (node[x].l >= node[x].r) return; int lx = LL(x); int rx = RR(x); node[x].mi = min( node[lx].mi, node[rx].mi); } void update(int left, int right, int x, int val) { if (node[x].l == left && node[x].r == right) { node[x].mi = val; return; } int lx = LL(x); int rx = RR(x); int mid = node[x].l + (node[x].r - node[x].l)/2; if (right <= mid) update(left, right, lx, val); else if (left > mid) update(left, right, rx, val); else { update(left, mid, lx, val); update(mid + 1, right, rx, val); } push_up( x); } int query(int left, int right, int x) { if (node[x].l == left && node[x].r == right) { return node[x].mi; } int mid = node[x].l + (node[x].r - node[x].l)/2; int lx = LL(x); int rx = RR(x); if (right <= mid) return query(left, right, lx); else if (left > mid) return query(left, right, rx); else return min( query(left, mid, lx), query(mid + 1, right, rx)); } void solve() { char str[40]; while (m--) { int x = 0, y = 0, ind; scanf("%s", str); if (str[0] == 'q') { ind = 0; while (!is_number(str[ind])) ind++; x = 0; while (is_number(str[ind])) { x *= 10; x += str[ind] - '0'; ind++; } while (!is_number(str[ind])) ind++; y = 0; while (is_number(str[ind])) { y *= 10; y += str[ind] - '0'; ind++; } printf("%d ", query( x, y, 1)); } else { ind = 0, tot = 0; while (str[ind] != ')') { if (is_number(str[ind])) { x = 0; while (is_number(str[ind])) { x *= 10; x += str[ind] - '0'; ind++; } tmp[tot++] = x; } else ind++; } int swap = arr[tmp[0]]; for (int i = 0; i < tot - 1; ++i) arr[tmp[i]] = arr[tmp[i+1]]; arr[tmp[tot - 1]] = swap; for (int i = 0; i < tot; ++i) { update( tmp[i], tmp[i], 1, arr[tmp[i]]); } } } } bool is_number(char ch) { if (ch >= '0' && ch <= '9') return true; return false; }