原题地址:http://codeforces.com/problemset/problem/380/A

让期末考试整的好久没有写题, 放假之后由于生病也没怎么做,新年的第一场CF也不是那么在状态,只过了div2的前两道题,第三题想到算法但是太困了没写对,刚刚把第三题A了很兴奋,赶快过来把解题报告写了。不得不说这道题还算有点水平

题目大意:

维护一个初始为空的序列,支持两种操作,共 m 个(1 <= m <= 10 ^ 5):

1 将一个数插入到数列的尾端(插入的数不大于10 ^ 5)

2 将数列的前 l 位复制 c 次,贴到数列的尾端(1 <= l <= 10 ^ 5, 1 <= c <= 10 ^ 4)

然后进行 n (1 <= n <= 10 ^ 5)次查询,每次给出一个数 x ,输出最终数列的第x位(所有查询数满足严格递增)

题目满足数据合法

题目分析:

这道题给人的第一反应是数据规模很大,直接模拟生成数列不仅会超时,而且会爆系统内存(最多大概可以有 10 ^ 9个数),所以我们着手去想其他的解题思路。

首先想到的是处理出每一个操作所生成的数列的位置(包括起始位置和终止位置)然后按照查询给出的位置 x 在操作序列中二分查找出生成包含 x 这一段的操作的位置,根据这个操作去计算位置x上的值。但是这样要考虑到一件事,如果生成 x 的操作是操作 2 , 那么由于操作 2 是复制当前数列的前l个数,而当前数列仍旧是未知的,也就是说我们还是需要再在前面的操作中二分,知道查到一个由操作一生成的点。这种做法直接导致复杂度无法估计,而且递归的编程难度加大,想法有点难实现。

接下来我们从范围入手,注意到操作二只会用到当前数列的前10 ^ 5个点,而数列中的点是不会修改的,所以我们萌生了这种想法:模拟出数列的前10 ^ 5个点,然后再查找生成 x 的对应操作。这样问题就简化很多了。

模拟之后的查找有两种方案,第一种还是二分,复杂度O(n log n)没问题,但是写起来稍微麻烦。后一种方法用到了题目中查询序列的递增顺序,直接线性地从先往后扫就行,复杂度是O(n + m)

细节处理:

1. 注意边界条件和循环退出条件

2.如果当前查到的点的位置小于10 ^ 5 直接输出模拟出来的数列中的对应位置值就可以了。

3.如果查到的位置对应操作为操作1,直接输出操作一的操作数值,如果为操作二需要计算一下取模(详见代码),特别注意取模得零的情况

 //date 20140114
#include <cstdio>
#include <cstring>
#include <iostream> using namespace std; const int maxm = ; inline int getint()
{
int ans(); char w = getchar();
while('' > w || w > '')w = getchar();
while('' <= w && w <= '')
{
ans = ans * + w - '';
w = getchar();
}
return ans;
} int n, m;
struct build
{
int ord, x, l, c;
long long a, b;
}hell[maxm];
int sq[maxm]; int main()
{
m = getint();
for(int i = ; i <= m; ++i)
{
hell[i].ord = getint();
if(hell[i].ord == ){
hell[i].x = getint();
hell[i].a = hell[i].b = hell[i - ].b + 1LL;
if(hell[i].a < maxm)sq[hell[i].a] = hell[i].x;
}
else{
hell[i].l = getint(); hell[i].c = getint();
hell[i].a = hell[i - ].b + 1LL;
hell[i].b = hell[i - ].b + (long long)hell[i].l * (long long)hell[i].c;
if(hell[i].a < maxm)
{
int now = hell[i].a;
for(int j = ; j <= hell[i].c && now < maxm; ++j)
for(int k = ; k <= hell[i].l && now < maxm; ++k)
sq[now++] = sq[k];
}
}
} n = getint();
int h = ; long long x;
for(int i = ; i <= n; ++i)
{
cin >> x;
while(!(hell[h].a <= x && hell[h].b >= x))++h;
if(x <= )printf("%d ", sq[x]);
else{
if((x - hell[h - ].b) % (long long)hell[h].l != )
cout << sq[(x - hell[h - ].b) % (long long)hell[h].l] << ' ';
else cout << sq[hell[h].l] << ' ';
}
}
return ;
}

总结:

这题就是想法和细节以及编程能力。

Codeforces 380A - Sereja and Prefixes的更多相关文章

  1. codeforces 380A Sereja and Prefixes (递归)

    题目: A. Sereja and Prefixes time limit per test 1 second memory limit per test 256 megabytes input st ...

  2. Codeforce 380A Sereja and Prefixes【二分】

    题意:定义两种操作 1 a ---- 向序列中插如一个元素a 2 a b ---- 将序列的前a个元素[e1,e2,...,ea]重复b次插入到序列中 经过一列操作后,为处于某个位置p的元素是多少.数 ...

  3. codeforces 314E Sereja and Squares

    discription Sereja painted n points on the plane, point number i (1 ≤ i ≤ n) has coordinates (i, 0). ...

  4. Codeforces 425A Sereja and Swaps(暴力枚举)

    题目链接:A. Sereja and Swaps 题意:给定一个序列,能够交换k次,问交换完后的子序列最大值的最大值是多少 思路:暴力枚举每一个区间,然后每一个区间[l,r]之内的值先存在优先队列内, ...

  5. codeforces 425C Sereja and Two Sequences(DP)

    题意读了好久才读懂....不知道怎么翻译好~~请自便~~~ http://codeforces.com/problemset/problem/425/C 看懂之后纠结好久...不会做...仍然是看题解 ...

  6. codeforces B. Sereja and Stairs 解题报告

    题目链接:http://codeforces.com/problemset/problem/381/B 题目意思:给定一个m个数的序列,需要从中组合出符合楼梯定义 a1 < a2 < .. ...

  7. codeforces A. Sereja and Bottles 解题报告

    题目链接:http://codeforces.com/problemset/problem/315/A 题目意思:有n个soda bottles,随后给出这n个soda bottles的信息.已知第 ...

  8. codeforces C. Sereja and Swaps

    http://codeforces.com/contest/426/problem/C 题意:找出连续序列的和的最大值,可以允许交换k次任意位置的两个数. 思路:枚举区间,依次把区间内的比较小的数换成 ...

  9. CodeForces - 314C Sereja and Subsequences (树状数组+dp)

    Sereja has a sequence that consists of n positive integers, a1, a2, ..., an. First Sereja took a pie ...

随机推荐

  1. jQuery scroll(滚动)延迟加载

    延迟加载 $(window).scroll(function(){ var scrollHeight = $(document).height(); //文档高度 var scrollTop = $( ...

  2. Javascript中最常用的55个经典技巧

    Javascript中最常用的55个经典技巧1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table ...

  3. jquery checkBox的问题

    在新版的jquery中选择ckeckbox最好使用prop方法,否则会出现一些问题.比如手动点击取消,再使用代码全选或者反选时候就不好使啦!!!

  4. linux命令 chattr超级权限控件

    linux命令:chattr 1.作用 修改ext2和ext3文件系统属性(attribute),使用权限超级用户.   linux命令:chattr 1.作用修改ext2和ext3文件系统属性(at ...

  5. Spark Streaming揭秘 Day17 资源动态分配

    Spark Streaming揭秘 Day17 资源动态分配 今天,让我们研究一下一个在Spark中非常重要的特性:资源动态分配. 为什么要动态分配?于Spark不断运行,对资源也有不小的消耗,在默认 ...

  6. Pandas简易入门(二)

    目录:     处理缺失数据     制作透视图     删除含空数据的行和列     多行索引     使用apply函数   本节主要介绍如何处理缺失的数据,可以参考原文:https://www. ...

  7. CentOS7下源码安装mysql5.6

    目录 准备工作 运行环境 确认你的安装版本 下载mysql 安装mysql 准备安装环境 编译和安装 配置mysql 单实例配置      单实例配置方法          添加防火墙         ...

  8. 初次接触pyqt

    基本了解了pyqt的原理,到http://www.riverbankcomputing.co.uk/news下载安装好qt后,桌面上会出现Qt Designer. 我们可以利用它进行界面的设计,然后保 ...

  9. 汽车之家, 比亚迪等成为开源数据库SSDB的用户

    开源的 NoSQL 数据库 SSDB 已经一岁多了! 在这一年中, SSDB 不断被应用在众多业界知名互联网企业, 创业团队的产品中. 最近, 比亚迪汽车也成为 SSDB 的用户, 其将 SSDB 作 ...

  10. easy ui easyui-linkbutton 禁用、启用

    <a id="btn_update_Shop" name="btn_update_Shop" class="easyui-linkbutton& ...