UVA 12299 RMQ with Shifts(线段树)

来源:互联网 发布:男女互换灵魂的网络剧 编辑:程序博客网 时间:2024/05/01 18:27
题目大意:第一行输入两个整数(数据个数,操作个数),query(a,b)为查找区间a到b的最小值,并输出。shift(a,b,c,d...)为将a,b,c,d...全部循环左移。

解析:线段树的单点更新。

#include <cstdio>#include <cstring>#include <algorithm>#include <ctype.h>using namespace std;const int INF = 0x3f3f3f3f;const int N = 100005;int L[N << 2],R[N << 2],s[N << 2];int a[N],d[N];void build(int u,int l,int r) {if(l == r) { //当前是叶节点L[u] = R[u] = l;s[u] = a[l];return;}//非叶节点int mid = (l + r) / 2;build(u*2,l,mid);build(u*2+1,mid+1,r);L[u] = l;R[u] = r;s[u] = min(s[u*2],s[u*2+1]);}void modify(int u,int x,int v) {if(x == L[u] && x == R[u]) {s[u] = v;return;}int mid = (L[u] + R[u]) / 2;if(mid >= x) {modify(u*2,x,v);}else {modify(u*2+1,x,v);}s[u] = min(s[u*2],s[u*2+1]);}int query(int u,int l,int r) {if(l <= L[u] && R[u] <= r) {return s[u];}int mid = (L[u] + R[u]) / 2;int ret = INF;if(l <= mid) {ret = min(ret, query(u*2,l,r));}if(r > mid) {ret = min(ret, query(u*2+1,l,r));}return ret;}char cmd[1000];int read_line(char cmd[]) {int len = strlen(cmd);int tot = 0;int num = 0;for(int i = 6; i < len; i++) {if(isalnum(cmd[i])) {num = num * 10 + (cmd[i] - '0');}else {d[tot++] = num;num = 0;}}return tot;}int main() {int n,q;while(scanf("%d%d",&n,&q) != EOF) {for(int i = 1; i <= n; i++) {scanf("%d",&a[i]);}memset(s,0,sizeof(s));L[1] = 1;R[1] = n;build(1,L[1],R[1]);while(q--) {scanf("%s",cmd);if(cmd[0] == 'q') {int l,r;sscanf(cmd,"query(%d,%d)",&l,&r);printf("%d\n",query(1,l,r));}else {int tot = read_line(cmd);int tmp = a[d[0]];for(int i = 1; i < tot; i++) {modify(1,d[i-1],a[d[i]]);a[d[i-1]] = a[d[i]];}modify(1,d[tot-1],tmp);a[d[tot-1]] = tmp;}}}return 0;}


0 0
原创粉丝点击