湖南省第七届大学生计算机程序设计竞赛 RMQ with Shifts (线段树)

RMQ with Shifts

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

描述

    In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R) (L<=R), 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<=120,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 30 characters, with no space characters inside. All operations are guaranteed
to be valid. Warning: The dataset is large, better to use faster I/O methods.
输出
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 
来源

湖南省第七届大学生计算机程序设计竞赛

算是线段树的基础题了,单点更新,基本的操作都没有什么难度,这道题主要要搞清楚那个循环左移的,对于这个操作,开始不知道怎么操作,还有输入的时候也要注意,考验很多细节的处理,还有处理问题的一些技巧,对于这种变形还要多加练习,积累一些处理问题的经验。

可以归纳总结自己的一些模板,很多基本操作的时候可以套用,具体问题都是考察一些细节和技巧的处理。

下面是代码:

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
int a[maxn];
int index[maxn];
struct node//线段树的节点结构
{
    int l,r,val;
}t[maxn*3];
void build(int root,int l,int r)//建树
{
    t[root].l=l;
    t[root].r=r;
    if(l==r)
    {
        t[root].val=a[l];
        return ;
    }
    int m=(l+r)>>1;
    build(root<<1,l,m);
    build(root<<1|1,m+1,r);
    t[root].val=min(t[root<<1].val,t[root<<1|1].val);
}
void update(int root,int l,int r,int val)//更新操作
{
    if(t[root].l==l && t[root].r==r)
    {
        t[root].val=val;
        return ;
    }
    int m=(t[root].l+t[root].r)>>1;
    if(m>=r) update(root<<1,l,r,val);
    else
        update(root<<1|1,l,r,val);
    t[root].val=min(t[root<<1].val,t[root<<1|1].val);
}
int query(int root,int l,int r)//查询
{
    if(t[root].l==l && t[root].r==r)
        return t[root].val;
    int m=(t[root].l+t[root].r)>>1;
    if(m>=r) return query(root<<1,l,r);
    else if(l>m) return query(root<<1|1,l,r);
    else
        return min(query(root<<1,l,m),query(root<<1|1,m+1,r));
}
int main()
{
     int n,q,l,r;
     char s[100];
     scanf("%d%d",&n,&q);
     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     build(1,1,n);
     for(int i=0;i<q;i++)
     {
         scanf("%s",s);
         if(s[0]=='q')
         {
            sscanf(s+5,"(%d,%d)",&l,&r);
            printf("%d\n",query(1,l,r));
         }
         else//主要是对循环左移的操作
         {
             int k,l=0,t=0;
             for(k=0;s[k];k++)  if(s[k]=='(') break;
             for(int j=k+1;s[j];j++)//处理输入的字符,提出需要的数字
             {
                 while(s[j]!=',' && s[j]!=')')
                 {
                     t=t*10+s[j]-'0';
                     j++;
                 }
                 index[l++]=t;
                 t=0;
             }
            t=a[index[0]];
            for(int k=0;k<l;k++)//处理循环左移
            {
                if(k==0) update(1,index[l-1],index[l-1],a[index[0]]);
                else
                update(1,index[k-1],index[k-1], a[index[k]]) ;
            }
             for(int k=0;k<l-1;k++)
                a[ index[k]]=a[index[k+1]];
            a[index[l-1]]=t;
         }
     }
    return 0;
}
时间: 2024-08-05 03:59:13

湖南省第七届大学生计算机程序设计竞赛 RMQ with Shifts (线段树)的相关文章

湖南省第七届大学生计算机程序设计竞赛 报数游戏

报数游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述     n 个人站成一行玩一个报数游戏.所有人从左到右编号为 1 到 n.游戏开始时,最左边的人报 1,他右边的人报 2,编号为 3 的人报 3,等等.当编号为 n 的人(即最右边的人)报完 n 之后,轮到他左边的人(即编号为n-1 的人)报 n+1,然后编号为 n-2 的人报 n+2,以此类推.当最左边的人再次报数之后,报数方向又变成从左到右,依次类推. 为了防止游戏太无聊,报数时有一个特例:如果应该报的数

湖南省第七届大学生计算机程序设计竞赛 多连块拼图 (模拟)

多连块拼图 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述     多连块是指由多个等大正方形边与边连接而成的平面连通图形.         ---- 维基百科 给一个大多连块和小多连块,你的任务是判断大多连块是否可以由两个这样的小多连块拼成.小多连块只能平移,不能旋转或者翻转.两个小多连块不得重叠.左下图是一个合法的拼法,但右边两幅图都非法.中间那幅图的问题在于其中一个小多连块旋转了,而右图更离谱:拼在一起的那两个多连块根本就不是那个给定的小多连块(给定的小多连块

湖南省第十届大学生计算机程序设计竞赛:酷酷的单词

1505: 酷酷的单词 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 237 Solved: 88 [Submit][Status][Web Board] Description 输入一些仅由小写字母组成的单词.你的任务是统计有多少个单词是"酷"的,即每种字母出现的次数都不同. 比如ada是酷的,因为a出现2次,d出现1次,而1和2不同.再比如,banana也是酷的,因为a出现3次,n出现2次,b出现1次.但是,bbacccd不是酷的,因

湖南省第十三届大学生计算机程序设计竞赛 Football Training Camp 贪心

2007: Football Training Camp[原创-转载请说明] Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 228     Solved: 30 Description 在一次足球联合训练中一共有n支队伍相互进行了若干场比赛. 对于每场比赛,赢了的队伍得3分,输了的队伍不得分,如果为平局则两支队伍各得1分. Input 输入包含不超过1000组数据. 每组数据的第

湖南省第六届大学生计算机程序设计竞赛---汽水瓶

1006: 汽水瓶 时间限制: 1 Sec  内存限制: 128 MB 提交: 3  解决: 3 [提交][状态][讨论版] 题目描写叙述 有这样一道智力题:"某商店规定:三个空汽水瓶能够换一瓶汽水.小张手上有十个空汽水瓶.她最多能够换多少瓶汽水喝?"答案是5瓶,方法例如以下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子. 然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板.假设小张手上有n

湖南省第六届大学生计算机程序设计竞赛---数字整除

1008: 数字整除 时间限制: 1 Sec  内存限制: 128 MB 提交: 6  解决: 4 [提交][状态][讨论版] 题目描述 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍.当且仅当差是17的倍数时,原数也是17的倍数 . 例如,34是17的倍数,因为3-20=-17是17的倍数:201不是17的倍数,因为20-5=15不是17的倍数.输入一个正整数n,你的任务是判断它是否是17的倍数. 输入 输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整

湖南省第六届大学生计算机程序设计竞赛---弟弟的作业

1007: 弟弟的作业 时间限制: 1 Sec  内存限制: 128 MB 提交: 3  解决: 3 [提交][状态][讨论版] 题目描述 你的弟弟刚做完了"100以内数的加减法"这部分的作业,请你帮他检查一下.每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数:c是弟弟算出的答案,可能是不超过200的非负整数,也可能是单个字符"?",表示他不会算. 输入 输入文件包含不超过100行,以文件结束符结尾.每

csu 1503: 点到圆弧的距离-湖南省第十届大学生计算机程序设计竞赛

就是--判断p与圆心的连线与圆的交点在不在圆弧上,在就是它到p的距离,不在就是p跟端点的最短距离 #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector>

湖南省第十届大学生计算机程序设计竞赛:残缺的棋盘

1511: 残缺的棋盘 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 169 Solved: 56 [Submit][Status][Web Board]Description] Input 输入包含不超过10000 组数据.每组数据包含6个整数r1, c1, r2, c2, r3, c3 (1<=r1, c1, r2, c2, r3, c3<=8). 三个格子A, B, C保证各不相同. Output 对于每组数据,输出测试点编号和最少步数.