51nod 1422(强行YY)

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

思路:

维护一个数组。由于这里的m是10^5,所以可以通过这个来处理。维护一个数组,这个数组每个都是一个node值。

struct node
{
    int flag;
    ll l;
    ll r;
    ll st;
    ll num;
};

flag表示是当个点还是循环。l,r表示当前数组第i为保存的是哪一个范围内的信息。st表示如果为循环的时候,前st个。num表示循环的次数。

这时候m次输入的信息都可以用这个来维护。

然后处理每次查询,对于第i次查询,可以先二分存信息的数组,找到哪个位置时l<=x && x <=r(x表示当前询问的位置)。然后当前需要查询的位置x就会更新为一个更加前面

的位置。这里其实就是递归处理。 终止条件,就是找到flag == 0,也就是说找到了这个点。 我觉得这个时间复杂度可以降到log(yy的)。跑出来的时间还是不错的。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<time.h>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define ll unsigned long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = 100010;
struct node
{
    int flag;
    ll l;
    ll r;
    ll st;
    ll num;
};
struct qnode
{
    int id;
    ll x;
    ll ans;
}q[MAXN];
node mp[MAXN];
int n,m;
bool cmp1(qnode fa,qnode fb)
{
    return fa.x < fb.x;
}
bool cmp2(qnode fa,qnode fb)
{
    return fa.id < fb.id;
}
int Search(ll x)
{
    int l,r,tm;
    l = 1,r = m;
    while(l <= r){
        tm = (l + r) >> 1;
        if(mp[tm].l <= x && mp[tm].r >= x){
            return tm;
        }
        else if(mp[tm].l > x){
            r = tm - 1;
        }
        else {
            l = tm + 1;
        }
    }
}
ll getans(int x)
{
    int p = Search(x);
    if(mp[p].r == x && mp[p].flag == 0){
        return mp[p].st;
    }
    ll tp = (x - mp[p].l + 1) % mp[p].st;
    if(tp == 0)tp = mp[p].st;
    return getans(tp);
}
void solve()
{
    ll p = 1;
    sort(q+1,q+n+1,cmp1);
    int i = 1;
    while(1){
        if(i > n)break;
        while(q[i].x > mp[p].r){
            p ++;
        }
        if(mp[p].r == q[i].x && mp[p].flag == 0){
            q[i].ans = mp[p].st;
        }
        else {
            int tp = (q[i].x - mp[p].l + 1) % mp[p].st;
            if(tp == 0)tp = mp[p].st;
            q[i].ans = getans(tp);
        }
        i ++;
    }
    sort(q+1,q+n+1,cmp2);
    for(int i = 1; i <= n; i++){
        if(i == 1)cout<<q[i].ans;
        else cout<<‘ ‘<<q[i].ans;
    }
    printf("\n");
}
int main()
{
    while(cin >>m){
        node tp;
        ll x,y,z;
        ll cnt;
        cnt = 0;
        for(ll i = 1; i <= m; i++){
            cin >>z;
            if(z == 1){
                cin >>y;
                tp.flag = 0;
                tp.l = cnt + 1;
                tp.r = cnt + 1;
                tp.st = y;
                tp.num = 0;
                cnt ++;
                mp[i] = tp;
            }
            else {
                cin >>x >>y;
                tp.flag = 1;
                tp.l = cnt + 1;
                tp.r = 1LL * x * y + cnt;
                tp.st = x;
                tp.num = y;
                cnt += 1LL * x * y;
                mp[i] = tp;
            }
        }
        cin >>n;
        for(int i = 1; i <= n; i++){
            cin >>q[i].x;
            q[i].id = i;
        }
        solve();
    }
    return 0;
}
时间: 2024-10-14 05:21:07

51nod 1422(强行YY)的相关文章

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

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

【BZOJ】3757 苹果树

题意:n个节点的树,每个点有一种颜色.现有m种询问,每次询问x y a b表示x到y的路径上颜色的种数且a颜色看成b颜色.(n<=50000, m<=100000) #include <bits/stdc++.h> using namespace std; const int N=50005; int ihead[N], cnt, id[N], blo[N], f[N][16], dep[N], cal[N], col[N], st[N], n, m, Ans[N], ans, I

【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

[UOJ#278][UTR #2]题目排列顺序 试题描述 "又要出题了." 宇宙出题中心主任 -- 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这些题目的难度,然后再在汪洋大海中寻找符合该难度的题目. 题目的难度可以用一个 1 到 n 的排列 a1,-,an 表示,其中 ai 表示第 i 道题目在这 n 道题目中是第 ai 简单的题目,即恰有 ai?1 道题目比第 i 道题目简单. 经验丰富的吉米多出题斯基早就悟出了一种科学地决定难

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP

想了好久啊.... 用了我感觉比较好写的一种(因为没写过维护凸包),另一种是维护凸包的做法,本质一样?推荐http://www.mamicode.com/info-detail-345781.html. 网上的大多数解法: DP:f[i]=max(f[j]+a*(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c) 显然复杂度不对. 那么假设j>k且f[j]优于f[k] f[j]-f[k]+a*(sum[j]^2-sum[k]^2)-b*(sum[j]-sum[k])>2*

清澄A1202&amp;Bzoj2201:彩色圆环

因为Bzoj是权限题,所以可以去清澄做一下 Sol 突然考了一道这样的题,考场上强行\(yy\)出来了 win下评测Long double爆零TAT 首先肯定是破环为链变成序列问题辣 那么就要求第一个的颜色和最后的颜色不同 怎么统计,枚举前面有多长和右面有多长长度相等 中间的强制第一个与枚举的前面不同,以及最后一个与枚举的后面(就是前面)不同 合起来就是答案 考虑中间的怎么算 设\(f[0/1][i]\)表示到第\(i\)个位置,颜色与枚举的前面相同(\(1\)),不同(\(0\))的期望得分

0922CSP-S模拟测试赛后总结

连发三篇爆炸实录我的心态竟然还这么好…… 昨天题目的D2.稍难. 这也不是我连续拿倒数第一的理由. T1不会.赛时硬写了一个30分的三次方暴力.还有一个地方写挂了.如果不是数据足够水我就爆零了. 也就是说我的11分subtask1还是捡来的. 最难过的是T2.T2写了乱搞(正解之一??).然而并没有调出来. 二维莫队.我写的很顺.没什么细节错误.然而, 我是在最后20分钟才开始打的.也就是说我最一开始并没有打二维莫队. 一方面是觉得这东西复杂度应该不对.另一方面,我不会离散化. 对.我不会离散化

51nod 算法马拉松4 B递归(YY)

递归 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 函数f(n,m) { 若n=1或m=1返回a[n][m]; 返回f(n-1,m)异或f(n,m-1); } 读入2<=n,m<=100 for i=2->100读入a[1][i] for i=2->100读入a[i][1] 输出f(n,m) 发现当n,m较大时程序变得异常缓慢. 小b经过一番思考,很快解决了这个问题. 这时小c出现了,我将n,m都增加131072,你还能解决吗? 相对的,我会读入2->13

51Nod 1515(并查集、set、离散化)

//代码还是YY学姐帮改的,自己从来没有真正A过几道题,不是看题解就是有BUG找不出,多久了还是改变不了这样的现状,或许ACM就是这么筛选人的吧.从5.24到11.24,再到又一年的5.24,可感觉后者比前者过得快多了.多读了一年的大学,完全没有了时间概念,不知道现在到底是大几了,不知道现在到底处在什么位置,不知道毕业后到底从不从事IT这行,一切都是未知的. 题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=15

51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛

OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就可以A.. 然后之后zcg以奇怪的二分方式发现了如何A掉第一题的第十个点(我记得貌似是什么第5000个数等于511? OwO 就这样没有任何思考含量全凭骗分黑科技过掉了第一题 OwO 然后zcg打开了第二题,发现第二题样例有点问题,然后就发了个帖子,直接去看第三题了 我去瞅了一眼,发现这不是gcd