NYOJ 1012 RMQ with Shifts (线段树)
- In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R)(L \leR), 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.
样例输入
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)
样例输出
1
4
6
分析:
对于一个下标从1到n的序列,主要有两种操作,一种是query(查询)某个区间内的最小值,另一种是shift(循环左移一位)就是将这些下标对应的值循环向左移动一位,当然第一位的值会移动到最后一位。我们首先肯定是将前一位的值更改为后一位,但是在更改最后一位的时候第一位的值已经改变了,所以应该将第一位的值提前存储下来。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<math.h>
using namespace std;
int a[100009];
struct Node
{
int left;///左区间
int right;///右区间
int num;///该区间内的最小值
} node[400009];
void build(int root,int le,int ri)
{
node[root].left=le;
node[root].right=ri;
if(le==ri)///左区间与右区间相等,相当于找到了某个特定的值
{
node[root].num=a[le];
return ;
}
int mid=(le+ri)/2;
build(root*2,le,mid);
build(root*2+1,mid+1,ri);
node[root].num=min(node[root*2].num,node[root*2+1].num);
}
void Update(int root,int n1,int n2)
{
if(node[root].left==n1&&node[root].right==n1)///先找到这个数字,然后把这个值更新了
{
node[root].num=n2;
return;
}
if(n1<=node[root*2].right)///该节点在左子树中
Update(root*2,n1,n2);
else if(n1>=node[root*2+1].left)///节点在右子树中
Update(root*2+1,n1,n2);
node[root].num=min(node[root*2].num,node[root*2+1].num);///取左右子树的较小值
}
int Query(int root,int le,int ri)
{
if(node[root].left==le&&node[root].right==ri)///找到特定的区间,返回值
{
return node[root].num;
}
else if(node[root*2].right>=ri)///区间在左子树中
{
return Query(root*2,le,ri);
}
else if(node[root*2+1].left<=le)///区间在右子树中
{
return Query(root*2+1,le,ri);
}
else
{
int mid=(node[root].left+node[root].right)/2;///左右子树中都有
int num1=Query(root*2,le,mid);
int num2=Query(root*2+1,mid+1,ri);
return min(num1,num2);
}
}
int main()
{
//freopen("1.txt","r",stdin);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
char ch[109];
build(1,1,n);
while(m--)
{
int b[1000];
int j=0;
int sum=0;
scanf(" %s",ch);
for(int i=6; ch[i]!='\0'; i++)///将每个数字提取出来
{
if(ch[i]>='0'&&ch[i]<='9')
{
sum=sum*10+ch[i]-'0';
}
else
{
if(ch[i]==','||ch[i]==')')
{
b[j++]=sum;
sum=0;
}
}
}
if(ch[0]=='q')
{
printf("%d\n",Query(1,b[0],b[1]));
}
else
{
int NUM=a[b[0]];///把第一位保存下来
for(int i=0; i<j-1; i++)///先把a数组更新了,再把树进行更新
a[b[i]]=a[b[i+1]];
a[b[j-1]]=NUM;
for(int i=0; i<j-1; i++)
{
Update(1,b[i],a[b[i]]);
}
Update(1,b[j-1],NUM);
}
}
return 0;
}
NYOJ 1012 RMQ with Shifts (线段树)的更多相关文章
- UVa 12299 RMQ with Shifts(线段树)
线段树,没了.. ----------------------------------------------------------------------------------------- # ...
- RMQ with Shifts(线段树)
RMQ with Shifts Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Pra ...
- TZOJ 4325 RMQ with Shifts(线段树查询最小,暴力更新)
描述 In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each que ...
- TOJ 4325 RMQ with Shifts / 线段树单点更新
RMQ with Shifts 时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte 描述 In the traditional RMQ (Range M ...
- nyoj 568——RMQ with Shifts——————【线段树单点更新、区间求最值】
RMQ with Shifts 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 In the traditional RMQ (Range Minimum Q ...
- RMQ问题(线段树+ST算法)
转载自:http://kmplayer.iteye.com/blog/575725 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ ...
- BZOJ 1012: [JSOI2008]最大数maxnumber 线段树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能: ...
- NYOJ 116 士兵杀敌 (线段树,区间和)
题目链接:NYOJ 116 士兵杀敌 士兵杀敌(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描写叙述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的 ...
- 1012: [JSOI2008]最大数maxnumber 线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=1012 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数 ...
随机推荐
- 课堂学习Scrum站立会议
项目名称:连连看游戏 小组成员:张政,张金生,李权,武志远 Master:张政 站立会议内容 1.已完成的内容 windows下的基本用户页面,实现了多个BUTTON下7*12的页面布局,但是出现了b ...
- 多线程---handlerthread
当我们需要工作线程来操作的时候,很多时候会有同步问题,UI更新问题. Handle机制就是为了解决这个问题而产生的. android允许每个线程都有自己的消息队列,同时也可以是主线程消息队列. 但是很 ...
- IDEA使用switch传入String编译不通过
今天在使用IDEA的时候,用到switch分支语句,传入String参数的时候一直报错,下面是源码报错截图: 看错误提示并没有提到switch支持String类型,不过ava1.7之后就支持Strin ...
- bug:margin塌陷
margin塌陷:两个嵌套的div,内部div的margin-top失效,内部对于外部的div并没有产生一个margin值,而是外部的div相对于上面的div产生了一个margin值. 弥补方法: 1 ...
- 【刷题】BZOJ 1211 [HNOI2004]树的计数
Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要 ...
- Linux内核设计第三周学习总结 跟踪分析Linux内核的启动过程
陈巧然 原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验步骤 登陆实验楼虚 ...
- Linux之多线程20160705
简单介绍一下多线程的API,线程的概念类似与一个任务或者说一个函数,线程一旦被创建就会运行,具体使用方法可以在Linux下使用man 命令查看: pthread_t:线程ID pthread_attr ...
- Codeforces Global Round 2 题解
Codeforces Global Round 2 题目链接:https://codeforces.com/contest/1119 A. Ilya and a Colorful Walk 题意: 给 ...
- 使用jconsole工具来监控java运行情况
参考:http://blog.163.com/lucas_nina/blog/static/185960149201493034258448/ 经验证OK jconsole是jdk自带的工具. ...
- vue 拦截器
拦截器:请求发送之前和请求返回之后的处理 使用:1.config---dev.env.js 开发环境配置 2. prod.env.js 生产 API:'http://www.wpdic.com' 3. ...