题目链接:http://acm.hust.edu.cn/vjudge/problem/23591
大意:给出n个数q个询问。对于query(a,b),输出区间(a,b)的数的最小值;对于shift(a0,a1,a2,......,an),则将第a1个数的值赋给a0,第a2个数赋给a1......,第an个数赋给an-1,第a0个数赋给an
思路:
线段树模板题,为了修改方便,可以先用一个额外的数组将这n个数保存下来。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int INF = 1e9 + 10;
int min_[maxn<<2],arr[maxn];
int n,q;
int ql,qr;
vector<int> Query_(char *s)
{
vector<int> ans;
ans.clear();
int len = strlen(s);
int sum = 0;
for (int i = 0; i < len; i++) {
if (s[i] == ')' || s[i] == ',') {
ans.push_back(sum);
sum = 0;
}
else if (isdigit(s[i])) {
sum *= 10;
sum += s[i]-'0';
}
}
return ans;
}
void build(int l, int r, int rt)
{
if (l == r) min_[rt] = arr[l];
else {
int m = (l + r) >> 1;
build(lson);
build(rson);
min_[rt] = min(min_[lc],min_[rc]);
}
}
int query(int l, int r, int rt)
{
if (ql <= l && r <= qr) return min_[rt];
int m = (l + r) >> 1;
int ans = INF;
if (ql <= m) ans = min(ans, query(lson));
if (m < qr) ans = min(ans,query(rson));
return ans;
}
void update(int p, int x, int l, int r, int rt)
{
if (l == r) min_[rt] = x;
else {
int m = (l + r) >> 1;
if (p <= m) update(p,x,lson);
else update(p,x,rson);
min_[rt] = min(min_[lc], min_[rc]);
}
}
int main()
{
scanf("%d%d",&n,&q);
for (int i = 1; i <= n; i++) scanf("%d",&arr[i]);
build(1,n,1);
while(q--) {
char s[50];
scanf("%s",s);
vector<int> ha = Query_(s);
if (s[0] == 'q') {
ql = ha[0];
qr = ha[1];
printf("%d\n",query(1,n,1));
}
else{
int t = arr[ha[0]];
int len = ha.size() - 1;
for (int i = 0; i < len; i++) {
update(ha[i],arr[ha[i+1]],1,n,1);
arr[ha[i]] = arr[ha[i+1]];
}
update(ha[len],t,1,n,1);
arr[ha[len]] = t;
}
}
}