51nod 1471 小S的兴趣

题面

小S喜欢有趣的事。但是,每个人的兴趣都是独特的。小S热衷于自问自答。有一天,小S想出了一个问题。

有一个包含n个正整数的数组a和针对这个数组的几个问题。这些问题有两种类型:

  1.  在数组下标l到r的部分上,将一个单元格循环移动到右端。即以下面方式重新分配数组上的元素。

a[l], a[l+1], ..., a[r-1], a[r] → a[r], a[l], a[l+1], ..., a[r-1].

2. 在数组下标l到r的部分上,计算有多少元素的值与k相等。

小S很喜欢这个问题并且很快解决了它,你是否能够解决它呢?

Input

第一行包含整数 n (1 ≤ n ≤ 10*5) —数组元素的数量。第二行包含 n 个整数a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ n)。

第三行包含唯一的整数 q (1 ≤ q ≤ 10*5) —问题的数量。接下来的q行包含了这些询问。

因为你需要在线回答这些问题,所以这些问题将会被编码。第一种类型的询问将会以以下形式给出: 1 Li Ri 。第二种类型的询问将会以以下形式给出: 2 Li Ri Ki 。所有输入的数字都是整数,它们满足以下条件:1 ≤ Li,Ri,Ki ≤ n.

为解码输入的问题,你需要按以下转换操作:

li = ((Li + lastans - 1) mod n) + 1;

ri = ((Ri + lastans - 1) mod n) + 1;

ki=((Ki + lastans - 1) mod n) + 1.

lastans 是到当前询问为止最后一个第二种类型的询问的答案 (初始, lastans = 0)。如果转换后, li 比 ri 大,你需要交换这两个数字。

Output

对于每一个第二种类型的问题以单独一行输出答案。

Input示例

7
6 6 2 7 4 2 5
7
1 3 6
2 2 4 2
2 2 4 7
2 2 2 5
1 2 6
1 1 4
2 1 7 3

Output示例

2
1
0
0

题解

这道题可以用分块做!(其实我就是想练习分块才来写的这道题……)

大约\(\sqrt n\)(因为担心空间爆炸,我取的是400个一块)分成一块,每块内部是一个链表。对于每一块,记录某数在其中出现的次数。

当进行修改的时候,把右端点上的元素拿下来,插到左端点前面即可。但是单纯这样做,可能会导致有的块变大、有的块变小,不利于时间复杂度的稳定,于是把区间中间的每一块最右边的元素拿下来,插到下一个块的左端点前面,这样每次修改时块的大小不会改变。

注意可能出现修改区间的 l, r 相等的情况——对于我的代码,这里不特判的话链表操作就会GG……

#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
bool read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
else if(c == EOF) return 0;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
return 1;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int M = 400, N = 1e5+400;
int n, q, a[N];
int st[N/M], ed[N/M], pre[N], nxt[N];
int blk[N], beg[N];
// 使用链表存储每一块内部信息
// blk是原来某一编号的元素的所在的位置
int cnt[N/M][N], ans; // 记录每一块内每个数有多少 void erase(int x){ //删除元素x
pre[nxt[x]] = pre[x];
nxt[pre[x]] = nxt[x];
cnt[blk[x]][a[x]]--;
}
void insert(int x, int y){ //在x前面插入y(同一块)
pre[y] = pre[x];
nxt[y] = x;
nxt[pre[x]] = y;
pre[x] = y;
blk[y] = blk[x];
cnt[blk[y]][a[y]]++;
}
int find(int x){ //找到第x个元素
int b = 1;
while(b < blk[n] && beg[b + 1] <= x) b++;
int ret = nxt[st[b]], pos = beg[b];
while(pos < x) pos++, ret = nxt[ret];
return ret;
}
void change(int l, int r){
int left = find(l), right = find(r);
int b1 = blk[left], b2 = blk[right];
erase(right);
insert(left, right);
for(int b = b1; b < b2; b++){
int x = pre[ed[b]];
erase(x);
insert(nxt[st[b + 1]], x);
}
}
int query(int l, int r, int x){
int left = find(l), right = find(r);
int b1 = blk[left], b2 = blk[right];
int ret = 0;
if(b1 == b2){
for(int i = left; i != nxt[right]; i = nxt[i])
if(a[i] == x) ret++;
return ret;
}
for(int pos = beg[b1 + 1] - 1, i = pre[ed[b1]]; pos >= l; pos--, i = pre[i])
if(a[i] == x) ret++;
for(int pos = beg[b2], i = nxt[st[b2]]; pos <= r; pos++, i = nxt[i])
if(a[i] == x) ret++;
for(int b = b1 + 1; b < b2; b++)
ret += cnt[b][x];
return ret;
}
int main(){
read(n);
for(int i = 1; i <= n; i++){
read(a[i]);
pre[i] = i - 1, nxt[i] = i + 1, blk[i] = (i - 1) / M + 1;
if(i % M == 1)
beg[blk[i]] = i, st[blk[i]] = n + blk[i], pre[i] = st[blk[i]], nxt[st[blk[i]]] = i;
if(i % M == 0 || i == n)
ed[blk[i]] = n + blk[i], nxt[i] = ed[blk[i]], pre[ed[blk[i]]] = i;
cnt[blk[i]][a[i]]++;
}
beg[blk[n] + 1] = n + 1;
read(q);
while(q--){
int op, l, r, x;
read(op), read(l), read(r);
l = (l + ans - 1) % n + 1;
r = (r + ans - 1) % n + 1;
if(l > r) swap(l, r);
if(op == 1 && l != r)
change(l, r);
else if(op == 2){
read(x);
x = (x + ans - 1) % n + 1;
write(ans = query(l, r, x)), enter;
}
}
return 0;
}

51nod 1471 小S的兴趣 | 分块 链表的更多相关文章

  1. 51nod 1471 小S的兴趣 sqrt

    小S喜欢有趣的事.但是,每个人的兴趣都是独特的.小S热衷于自问自答.有一天,小S想出了一个问题. 有一个包含n个正整数的数组a和针对这个数组的几个问题.这些问题有两种类型: 1.      在数组下标 ...

  2. 51nod1471 小S的兴趣

    题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 320 小S喜欢有趣的事.但是,每个人的兴趣都是独特的.小S热衷于自问自答.有一天,小S想出了一个问题 ...

  3. 【CF896E】Welcome home, Chtholly 暴力+分块+链表

    [CF896E]Welcome home, Chtholly 题意:一个长度为n的序列ai,让你支持两种操作: 1.l r x:将[l,r]中ai>x的ai都减去x.2.l r x:询问[l,r ...

  4. bzoj 3781: 小B的询问 分块

    3781: 小B的询问 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 196  Solved: 135[Submit][Status] Descrip ...

  5. 51nod 1589 移数博弈【桶排序+链表】

    1589 移数博弈 基准时间限制:1 秒 空间限制:262144 KB 分值: 80 难度:5级算法题   小A和小B在玩一个游戏. 他们拥有一个数列. 小A在该数列中选择出最大的那个数,然后移出该数 ...

  6. 【BZOJ4548】小奇的糖果 set(链表)+树状数组

    [BZOJ4548]小奇的糖果 Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的 ...

  7. 51nod 1631 小鲨鱼在51nod小学

    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依靠算法方面的特长,在班里担任了许多职务.   ...

  8. Codeforces 455D 分块+链表

    题意: 给定一个长度为 N 的序列两种操作1 l r 将[l,r]的数向右循环移位 2 l r 询问[l,r]内有多少个数等于 k其中 N,Q≤105,ai≤N 强制在线 思路: 1. 每块用一个链表 ...

  9. AcWing 251. 小Z的袜子| 分块+莫队

    传送门 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿. 终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命. 具体来说,小Z把这N只袜子从 ...

随机推荐

  1. MapReduce 基础学习

      什么是MapReduce? mapreduce 是一种软件框架 mapreduce job将任务分解为独立的块儿到不同的map task,进行并行处理: map任务输出会做相应的排序处理,并作为r ...

  2. Netty源码分析第4章(pipeline)---->第2节: handler的添加

    Netty源码分析第四章: pipeline 第二节: Handler的添加 添加handler, 我们以用户代码为例进行剖析: .childHandler(new ChannelInitialize ...

  3. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第5节: 同线程回收对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第五节: 同线程回收对象 上一小节剖析了从recycler中获取一个对象, 这一小节分析在创建和回收是同线程的 ...

  4. CocoStuff—基于Deeplab训练数据的标定工具【五、训练成果分析】

    一.说明 本文为系列博客第五篇,主要展示训练的结果,以及对训练进行分析. *注:暂未进行大量的数据训练以及IoU测算,目前只做到使用Matlab将训练结果的mat文件可视化. 二. *占坑

  5. 搭建Harbor私有镜像仓库--v1.5.1

     搭建Harbor私有镜像仓库--v1.5.1 1.介绍 Docker容器应用的开发和运行离不开可靠的镜像管理,虽然Docker官方也提供了公共的镜像仓库,但是从安全和效率等方面考虑,部署我们私有环境 ...

  6. AlexNet——ImageNet Classification with Deep Convolutional Neural Networks

    1. 摘要 本文的模型采用了 5 层的卷积,一些层后面还紧跟着最大池化层,和 3 层的全连接,最后是一个 1000 维的 softmax 来进行分类. 为了减少过拟合,在全连接层采取了 dropout ...

  7. Solidity 神器Remix

    1 功能 这里我们使用在线编译器,打开网址 https://ethereum.github.io/browser-solidity 1.1 文件夹管理 最左边是文件夹管理,里面列出了当前工作区里的文件 ...

  8. 哪些场景下无法获得上一页referrer信息

    哪些场景下无法获得上一页referrer信息 直接在浏览器地址栏中输入地址: 使用 location.reload() 刷新(location.href 或者  location.replace()  ...

  9. (第六周)课上Scrum站立会议演示

    组名:连连看 组长:张政 组员:张金生.李权.武志远 时间:2016.10.13   20:20——20:40 会议内容: 已完成的内容: 1.选定编译语言,安装软件并配置环境,完成了游戏的基本模型. ...

  10. Scrum Meeting 12 -2014.11.18

    今天的任务都比较顺利,测试暂时还没发现特别的问题. Member Today’s task Next task 林豪森 与其他小组商讨整合问题 与其他小组商讨整合问题 宋天舒 测试项目功能实现 测试项 ...