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. 最近遇到的几个问题,关于Unity脚本在Inspector视图中前面没有勾选框的问题

    1.为什么在Inspector视图中有的脚本前面有勾选框,有的脚本前面没有? 当我想要禁用一个脚本时,发现脚本前面没有勾选框,有的却有. 解决办法:在脚本中添加start方法,然后就有勾选框了. 原因 ...

  2. CHAPTER 24 History of Our Planet 第24章 我们行星的历史

    CHAPTER 24 History of Our Planet 第24章 我们行星的历史 Uncovering the bones of ancient beasts is only part of ...

  3. 《how tomcat works》阅读笔记 - 2 - 门面设计模式,避免强制转换

    在第二章 2.3节中 try { servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) request ...

  4. https、ssl、tls协议学习

    一.知识准备 1.ssl协议:通过认证.数字签名确保完整性:使用加密确保私密性:确保客户端和服务器之间的通讯安全 2.tls协议:在SSL的基础上新增了诸多的功能,它们之间协议工作方式一样 3.htt ...

  5. Spring Data REST PATCH请求远程代码执行漏洞(CVE-2017-8046) 本地复现方法

      #1背景 Spring Data REST是Spring Data项目的一部分,可以轻松地在Spring Data存储库之上构建超媒体驱动的REST Web服务. 恶意的PATCH请求使用精心构造 ...

  6. plsql 不修改tnsnames.ora文件

    PLSQL 不修改tnsname直接连数据库的方式在PLSQL的Database中直接输入192.168.1.6:1521/VP.其中192.168.1.6为数据库的IP:1521为数据库端口:VP为 ...

  7. yarn (npm) 切换设置镜像源

    设置镜像源 1.查看一下当前源 yarn config get registry 2.切换为淘宝源 yarn config set registry https://registry.npm.taob ...

  8. TIME_WAIT 你好!

    [root@vm-10-124-66-212 ~]# netstat -an|awk -F ' ' '{print $NF}'|sort |uniq -c |sort -rn|more 5552 TI ...

  9. to_char

    to_date(to_char(to_date(#{conds.currentTime,jdbcType=VARCHAR},'YYYY-MM-DD hh24:mi:ss'),'hh24:mi:ss') ...

  10. sprint2(第六天)

    昨天休息一天,今天继续做任务. 燃尽图: