线段树变形 568,1012
2015-12-05 22:44
344 查看
描述
In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R)(LR),
we report the minimum value among A[L], A[L + 1], ..., A[R]. Note that the indices start from 1, i.e. the left-most element
is A[1].
In this problem, the array A is no longer static: we need to support another operation
shift(i1, i2, i3,..., ik)(i1 < i2 < ... < ik, k > 1)
we do a left ``circular shift" of A[i1], A[i2],
..., A[ik].
For example, if A={6, 2, 4, 8, 5, 1, 4}, then shift(2,
4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields 8, 6, 4, 5, 4, 1, 2.
输入There will be only one test case, beginning with two integers n, q ( 1<=n<=100, 000, 1<=q<=250, 000), the number of integers in array A, and the number of operations. The next line contains n positive integers not greater than 100,000, the initial elements
in array A. Each of the next q lines contains an operation. Each operation is formatted as a string having no more than 100 characters, with no space characters inside. All operations are guaranteed to be valid.输出For each query, print the minimum value (rather than index) in the requested range.写过好几遍,每次都有点小问题,注意!
//一定要注意数据范围!!数组一定要开够!!!细节太多了,这道题就是单点改变更新,思路不难,注意细节!!!
#include<cstdio>
#include<cstring>
using namespace std;
int a[100005];
int father[100005];
struct node{
int l;
int r;
int val;
}t[300005];
int ans;
int n;
int inf=2000000000;
inline int min(int a,int b){
return a>b?b:a;
}
int build(int root,int l,int r){
t[root].l=l;
t[root].r=r;
if (l==r){
father[l]=root;
t[root].val=a[l];
return a[l];
}
return t[root].val=min(build(root*2,l,(l+r)/2),build(root*2+1,(l+r)/2+1,r));
}
void update(int now){
while(now!=0){
t[now].val=min(t[now*2].val,t[now*2+1].val);
//cout<<t[now].val<<" " ;
now/=2;
}
}
int query(int root,int l,int r){
if (t[root].l==l&&t[root].r==r) {
return ans=min(ans,t[root].val);
}
if (l<=t[root*2].r){
if (r<=t[root*2].r) ans=query(root*2,l,r);
else ans=query(root*2,l,t[root*2].r);
}
if (r>=t[root*2+1].l){
if (l>=t[root*2+1].l) ans=query(root*2+1,l,r);
else ans=query(root*2+1,t[root*2+1].l,r);
}
return ans;
}
int main(){
int tt;
int tmp;
int m;
int v[100];
int count;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
char s[110];
int l,r;
while(m--){
scanf("%s",s);
if (s[0]=='q'){
ans=inf;
sscanf(s+5,"(%d,%d)",&l,&r);
printf("%d\n",query(1,l,r));
}
else {
count=0;
tmp=0;
for (int i=6;i<strlen(s);i++){
if(s[i]>='0'&&s[i]<='9'){
tmp=tmp*10+s[i]-'0';
}
else if(s[i]==','||s[i]==')'){
v[count++]=tmp;
tmp=0;
}
}
tt=t[father[v[0]]].val;
for (int i=0;i<count-1;i++){
t[father[v[i]]].val=t[father[v[i+1]]].val;
update( father[v[i]]/2 );
}
t[father[v[count-1]]].val=tt;
update(father[v[count-1]]/2);
}
}
}
In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R)(LR),
we report the minimum value among A[L], A[L + 1], ..., A[R]. Note that the indices start from 1, i.e. the left-most element
is A[1].
In this problem, the array A is no longer static: we need to support another operation
shift(i1, i2, i3,..., ik)(i1 < i2 < ... < ik, k > 1)
we do a left ``circular shift" of A[i1], A[i2],
..., A[ik].
For example, if A={6, 2, 4, 8, 5, 1, 4}, then shift(2,
4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields 8, 6, 4, 5, 4, 1, 2.
输入There will be only one test case, beginning with two integers n, q ( 1<=n<=100, 000, 1<=q<=250, 000), the number of integers in array A, and the number of operations. The next line contains n positive integers not greater than 100,000, the initial elements
in array A. Each of the next q lines contains an operation. Each operation is formatted as a string having no more than 100 characters, with no space characters inside. All operations are guaranteed to be valid.输出For each query, print the minimum value (rather than index) in the requested range.写过好几遍,每次都有点小问题,注意!
//一定要注意数据范围!!数组一定要开够!!!细节太多了,这道题就是单点改变更新,思路不难,注意细节!!!
#include<cstdio>
#include<cstring>
using namespace std;
int a[100005];
int father[100005];
struct node{
int l;
int r;
int val;
}t[300005];
int ans;
int n;
int inf=2000000000;
inline int min(int a,int b){
return a>b?b:a;
}
int build(int root,int l,int r){
t[root].l=l;
t[root].r=r;
if (l==r){
father[l]=root;
t[root].val=a[l];
return a[l];
}
return t[root].val=min(build(root*2,l,(l+r)/2),build(root*2+1,(l+r)/2+1,r));
}
void update(int now){
while(now!=0){
t[now].val=min(t[now*2].val,t[now*2+1].val);
//cout<<t[now].val<<" " ;
now/=2;
}
}
int query(int root,int l,int r){
if (t[root].l==l&&t[root].r==r) {
return ans=min(ans,t[root].val);
}
if (l<=t[root*2].r){
if (r<=t[root*2].r) ans=query(root*2,l,r);
else ans=query(root*2,l,t[root*2].r);
}
if (r>=t[root*2+1].l){
if (l>=t[root*2+1].l) ans=query(root*2+1,l,r);
else ans=query(root*2+1,t[root*2+1].l,r);
}
return ans;
}
int main(){
int tt;
int tmp;
int m;
int v[100];
int count;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
char s[110];
int l,r;
while(m--){
scanf("%s",s);
if (s[0]=='q'){
ans=inf;
sscanf(s+5,"(%d,%d)",&l,&r);
printf("%d\n",query(1,l,r));
}
else {
count=0;
tmp=0;
for (int i=6;i<strlen(s);i++){
if(s[i]>='0'&&s[i]<='9'){
tmp=tmp*10+s[i]-'0';
}
else if(s[i]==','||s[i]==')'){
v[count++]=tmp;
tmp=0;
}
}
tt=t[father[v[0]]].val;
for (int i=0;i<count-1;i++){
t[father[v[i]]].val=t[father[v[i+1]]].val;
update( father[v[i]]/2 );
}
t[father[v[count-1]]].val=tt;
update(father[v[count-1]]/2);
}
}
}
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C++联合体转换成C#结构的实现方法
- C#实现的算24点游戏算法实例分析
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析