Codeforces 380A - Sereja and Prefixes
原题地址: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的更多相关文章
- codeforces 380A Sereja and Prefixes (递归)
题目: A. Sereja and Prefixes time limit per test 1 second memory limit per test 256 megabytes input st ...
- Codeforce 380A Sereja and Prefixes【二分】
题意:定义两种操作 1 a ---- 向序列中插如一个元素a 2 a b ---- 将序列的前a个元素[e1,e2,...,ea]重复b次插入到序列中 经过一列操作后,为处于某个位置p的元素是多少.数 ...
- codeforces 314E Sereja and Squares
discription Sereja painted n points on the plane, point number i (1 ≤ i ≤ n) has coordinates (i, 0). ...
- Codeforces 425A Sereja and Swaps(暴力枚举)
题目链接:A. Sereja and Swaps 题意:给定一个序列,能够交换k次,问交换完后的子序列最大值的最大值是多少 思路:暴力枚举每一个区间,然后每一个区间[l,r]之内的值先存在优先队列内, ...
- codeforces 425C Sereja and Two Sequences(DP)
题意读了好久才读懂....不知道怎么翻译好~~请自便~~~ http://codeforces.com/problemset/problem/425/C 看懂之后纠结好久...不会做...仍然是看题解 ...
- codeforces B. Sereja and Stairs 解题报告
题目链接:http://codeforces.com/problemset/problem/381/B 题目意思:给定一个m个数的序列,需要从中组合出符合楼梯定义 a1 < a2 < .. ...
- codeforces A. Sereja and Bottles 解题报告
题目链接:http://codeforces.com/problemset/problem/315/A 题目意思:有n个soda bottles,随后给出这n个soda bottles的信息.已知第 ...
- codeforces C. Sereja and Swaps
http://codeforces.com/contest/426/problem/C 题意:找出连续序列的和的最大值,可以允许交换k次任意位置的两个数. 思路:枚举区间,依次把区间内的比较小的数换成 ...
- CodeForces - 314C Sereja and Subsequences (树状数组+dp)
Sereja has a sequence that consists of n positive integers, a1, a2, ..., an. First Sereja took a pie ...
随机推荐
- wampsever在win10中安装扩展掉坑
1.必须要退出wampserver 2.php pecl + 3.wampserver 64 3.0.6
- liger grid loadData
function fn_Search() { var beginDt = $("#txtBegin").val(); var endDt = $("#txtEnd&quo ...
- win8安装python环境和pip & easy_install工具
最近在学python,2.7.6的版本 首先安装python2.7 官网下载地址https://www.python.org/downloads/ 下载相应版本即可,应该是一个msi的文件,默认安装到 ...
- .NET基础之自定义泛型
在.NET中泛型使用非常频繁,在控制台应用程序中,默认的引入了System.Collection.Generics名称空间,其中就提供了我们经常使用的泛型:List<T>和Dictiona ...
- FPGA位宽的转换和定义
数字表达式的定义<位宽><进制><数字>,这是一种全面的描述方式 例如:如果我要定义一个变量counter = 5000 0000 ,10进制数:那么他的位宽应该是 ...
- install ruby and ruby gem
sudo apt-get install ruby #find an folder and: git clone https://github.com/rubygems/rubygems.git cd ...
- BZOJ 1588 营业额统计 Splay
主要操作为Splay中插入节点,查找前驱和后继节点. 1: #include <cstdio> 2: #include <iostream> 3: #include <c ...
- PHP截取字符串,获取长度,获取字符位置的函数
strstr(string,string) = strchr(,) //从前面第一次出现某个字符串的地方截取到最后strrchr(string,string) //从某个字符串从最后出现的位置截取到结 ...
- httpsclient 自动获取证书 无证书访问 验证过能直接用
首先实现写一个 实现接口SecureProtocolSocketFactory的类. /** *ClassName: bcde *date: 2015年2月26日 下午4:51:01 * *@auth ...
- python time相关操作
1.获取当前时间的两种方法: 代码如下: import datetime,timenow = time.strftime("%Y-%m-%d %H:%M:%S")print now ...