51Nod 1422 沙拉酱前缀 二分查找

1422 沙拉酱前缀

题目来源: CodeForces

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题

 收藏

 关注

沙拉酱非常喜欢数字序列。这正是他要弄一个关于构造序列的算法的原因。

沙拉酱拿了一张白纸。然后他开始用m个步骤来制作一个序列。每一步他要么向这个序列的末尾添加一个数字,要么拿这个序列的开头l个数字,然后在末尾添加c次。对于第二种操作,一般的,如果当前序列是 a1,a2,...,an ,那么经过操作之后序列将变成 a1,a2,...,an[,a1,a2,...,al]  (方括号里面的内容会重复c次)。

一天过去了,沙拉酱也完成了他的序列。现在他想知道某个位置是什么数字。

Input

单组测试数据。
第一行包含一个整数m (1 ≤ m ≤ 10^5),表示构造序列的步骤数目。
接下来m行包含每一个步骤的信息。第一个数字是类型(1或2)。类型1表示在序列后面加一个数字,这种情况下后面会跟一个整数xi (1 ≤ xi ≤ 10^5),表示被加在后面的数字。类型2表示复制一段长度为 li 前缀然后接到后面 ci 次,这种情况下后面会跟两个整数 li, ci(1 ≤ li ≤ 10^5, 1 ≤ ci ≤ 10^4),li 是前缀的长度,ci是复制的次数。输入中保证li不会大于当前序列的长度。

接下来一行包含一个整数n (1 ≤ n ≤ 10^5),表示查询的数量。接下来一行中包含n个正整数,每一个整数表示要查询的位置。题目保证这些数字大小不会超过序列的长度。序列的下标从1开始。

Output

对于每一个查询,输出对应查询位置的数字。两个查询之间用空格分开。具体格式看样例。

Input示例

6
1 1
1 2
2 2 1
1 3
2 5 2
1 4
16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Output示例

1 2 1 2 3 1 2 1 2 3 1 2 1 2 3 4

我真是好天真 读完题目 我竟然用string 来模拟这个过程  TIE是不存在的 可是却炸了string

正解是二分 记录每次操作和每次操作产生的数的个数 对于每次查询的位置x 二分这个位置出现在第几次操作如果 这个操作是增加一个数 就输出这个增加的数 如果这是复制一个序列 就找这个位置上的数 在第一次复制中的位置 然后再去继续二分查找

 1 #include <cctype>
 2 #include <cstdio>
 3 #include <algorithm>
 4
 5 using namespace std;
 6
 7 typedef long long LL;
 8 const int MAXN=100010;
 9
10 int n,q,opre;
11
12 int a[MAXN][3];
13
14 LL b[MAXN];
15
16 inline void read(int&x) {
17     int f=1;register char c=getchar();
18     for(x=0;!isdigit(c);c==‘-‘&&(f=-1),c=getchar());
19     for(;isdigit(c);x=x*10+c-48,c=getchar());
20     x=x*f;
21 }
22
23 inline void readL(LL&x) {
24     int f=1;register char c=getchar();
25     for(x=0;!isdigit(c);c==‘-‘&&(f=-1),c=getchar());
26     for(;isdigit(c);x=x*10+c-48,c=getchar());
27     x=x*f;
28 }
29
30 int hh() {
31     read(n);
32     for(int y,z,i=1;i<=n;++i) {
33         read(a[i][0]);
34         if(a[i][0]==1) {
35             read(a[i][1]);
36             b[i]=b[i-1]+1;
37         }
38         else {
39             read(a[i][1]);read(a[i][2]);
40             b[i]=b[i-1]+(LL)a[i][1]*a[i][2];
41         }
42     }
43     read(q);
44     LL x;
45     for(int i=1;i<=q;++i) {
46         readL(x);
47         while(true) {
48             opre=lower_bound(b+1,b+1+n,x)-b;
49             if(a[opre][0]==1) {
50                 printf("%d ",a[opre][1]);
51                 break;
52             }
53             else x=(x-b[opre-1]-1)%a[opre][1]+1;
54         }
55     }
56     return 0;
57 }
58
59 int sb=hh();
60 int main(int argc,char**argv) {;}

代码

时间: 2024-10-13 22:25:47

51Nod 1422 沙拉酱前缀 二分查找的相关文章

51nod 1422(强行YY)

1422 沙拉酱前缀 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 沙拉酱非常喜欢数字序列.这正是他要弄一个关于构造序列的算法的原因. 沙拉酱拿了一张白纸.然后他开始用m个步骤来制作一个序列.每一步他要么向这个序列的末尾添加一个数字,要么拿这个序列的开头l个数字,然后在末尾添加c次.对于第二种操作,一般的,如果当前序列是 a1,a2,...,an ,那么经过操作之后序列将变成 a1,a2,...,an[,a1

51 nod 1624 取余最长路 思路:前缀和 + STL(set)二分查找

题目: 写这题花了我一上午时间. 下面是本人(zhangjiuding)的思考过程: 首先想到的是三行,每一行一定要走到. 大概是这样一张图 每一行长度最少为1.即第一行(i -1) >= 1,第二行 (j - i) >= 1,第三行 (n - j) >= 1. 我们要求的就是这条路径上的和. 我们发现只要 i 和 j 固定了,结果就固定了. 如果每次都要重新求和的话时间复杂度肯定不够,所以我这个时候想到了前缀和. 用sum[a][b]表示第a行(总共只有3行)前b个数字的和. 第一行可

POJ——3061Subsequence(尺取法或二分查找)

Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11224   Accepted: 4660 Description A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) ar

【bzoj4012】[HNOI2015]开店 动态树分治+二分查找

题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群.很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n个地方,编号为 1 到 n,被 n-1 条带权的边连接起来.每个地方都住着一个妖怪,其中第 i 个地方的妖怪年龄是 x_i.妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻.所以这个树所有顶点的

SPOJ TEMPLEQ - Temple Queues(二分查找+树状数组)

题意: 有N个队伍(1 <= N <= 100,000),每个队伍开始有ai个人[0 <= ai<= 100,000,000],有Q个操作[0<=Q<= 500,000] 操作分为三种,1 A:表示在第A个队列加一个人. 2 X:表示求长度大于等于X队列数量.3 Y:表示所有长度大于等于Y的队列减去一个人. 题解: 把各个队列按长度排序 用差分数列来维护这个数组,这样求每个队列的长度就是求前缀和.每次求长度的复杂度是lgn,因为队列是按长度排序的,所以可以通过二分查找到

51nod 1105---二分套二分

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105 题意a序列和b序列,ab序列是 a和b两两组合,问你ab中第k大是多少.. 这题是个二分套二分,是个二分好题..为什么好呢,因为这个二分容易写残疾啊...(总之就是我太弱了 接下来分析一下这个题的解法和要注意的地方. 一个显然的方法就是二分答案了,然后判断mid是第几大就可以了.. 但是,仔细一想?咦..会不会二分的答案其实不是ab数组里面的呢?会不会ab里面有很

二分查找

递归版(在区间[x, y)中找v的位置) 1 //递归版二分查找 2 int bsearch(int * A, int x, int y, int v) 3 { 4 5 if(v<a[x] || v>a[y-1]) return -1; 6 int m = x + (y-x)/2; //此处能不能用int m = (x+y)/2,需要仔细考虑(暂时想不到原因) 7 if(A[m]==v) return m; 8 else if(A[m]>v) return bsearch(A, x, m

二分查找总结

最近刷leetcode和lintcode,做到二分查找的部分,发现其实这种类型的题目很有规律,题目大致的分为以下几类: 1.最基础的二分查找题目,在一个有序的数组当中查找某个数,如果找到,则返回这个数在数组中的下标,如果没有找到就返回-1或者是它将会被按顺序插入的位置.这种题目继续进阶一下就是在有序数组中查找元素的上下限.继续做可以求两个区间的交集. 2.旋转数组问题,就是将一个有序数组进行旋转,然后在数组中查找某个值,其中分为数组中有重复元素和没有重复元素两种情况. 3.在杨氏矩阵中利用二分查

二分查找JAVA实现

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表.首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表.重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功. 一.概念 二分查