51nod 1471 小S的兴趣 | 分块 链表
51nod 1471 小S的兴趣
题面
小S喜欢有趣的事。但是,每个人的兴趣都是独特的。小S热衷于自问自答。有一天,小S想出了一个问题。
有一个包含n个正整数的数组a和针对这个数组的几个问题。这些问题有两种类型:
在数组下标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的兴趣 | 分块 链表的更多相关文章
- 51nod 1471 小S的兴趣 sqrt
小S喜欢有趣的事.但是,每个人的兴趣都是独特的.小S热衷于自问自答.有一天,小S想出了一个问题. 有一个包含n个正整数的数组a和针对这个数组的几个问题.这些问题有两种类型: 1. 在数组下标 ...
- 51nod1471 小S的兴趣
题目来源: CodeForces 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 320 小S喜欢有趣的事.但是,每个人的兴趣都是独特的.小S热衷于自问自答.有一天,小S想出了一个问题 ...
- 【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 ...
- bzoj 3781: 小B的询问 分块
3781: 小B的询问 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 196 Solved: 135[Submit][Status] Descrip ...
- 51nod 1589 移数博弈【桶排序+链表】
1589 移数博弈 基准时间限制:1 秒 空间限制:262144 KB 分值: 80 难度:5级算法题 小A和小B在玩一个游戏. 他们拥有一个数列. 小A在该数列中选择出最大的那个数,然后移出该数 ...
- 【BZOJ4548】小奇的糖果 set(链表)+树状数组
[BZOJ4548]小奇的糖果 Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的 ...
- 51nod 1631 小鲨鱼在51nod小学
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依靠算法方面的特长,在班里担任了许多职务. ...
- Codeforces 455D 分块+链表
题意: 给定一个长度为 N 的序列两种操作1 l r 将[l,r]的数向右循环移位 2 l r 询问[l,r]内有多少个数等于 k其中 N,Q≤105,ai≤N 强制在线 思路: 1. 每块用一个链表 ...
- AcWing 251. 小Z的袜子| 分块+莫队
传送门 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿. 终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命. 具体来说,小Z把这N只袜子从 ...
随机推荐
- 最近遇到的几个问题,关于Unity脚本在Inspector视图中前面没有勾选框的问题
1.为什么在Inspector视图中有的脚本前面有勾选框,有的脚本前面没有? 当我想要禁用一个脚本时,发现脚本前面没有勾选框,有的却有. 解决办法:在脚本中添加start方法,然后就有勾选框了. 原因 ...
- CHAPTER 24 History of Our Planet 第24章 我们行星的历史
CHAPTER 24 History of Our Planet 第24章 我们行星的历史 Uncovering the bones of ancient beasts is only part of ...
- 《how tomcat works》阅读笔记 - 2 - 门面设计模式,避免强制转换
在第二章 2.3节中 try { servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) request ...
- https、ssl、tls协议学习
一.知识准备 1.ssl协议:通过认证.数字签名确保完整性:使用加密确保私密性:确保客户端和服务器之间的通讯安全 2.tls协议:在SSL的基础上新增了诸多的功能,它们之间协议工作方式一样 3.htt ...
- Spring Data REST PATCH请求远程代码执行漏洞(CVE-2017-8046) 本地复现方法
#1背景 Spring Data REST是Spring Data项目的一部分,可以轻松地在Spring Data存储库之上构建超媒体驱动的REST Web服务. 恶意的PATCH请求使用精心构造 ...
- plsql 不修改tnsnames.ora文件
PLSQL 不修改tnsname直接连数据库的方式在PLSQL的Database中直接输入192.168.1.6:1521/VP.其中192.168.1.6为数据库的IP:1521为数据库端口:VP为 ...
- yarn (npm) 切换设置镜像源
设置镜像源 1.查看一下当前源 yarn config get registry 2.切换为淘宝源 yarn config set registry https://registry.npm.taob ...
- TIME_WAIT 你好!
[root@vm-10-124-66-212 ~]# netstat -an|awk -F ' ' '{print $NF}'|sort |uniq -c |sort -rn|more 5552 TI ...
- to_char
to_date(to_char(to_date(#{conds.currentTime,jdbcType=VARCHAR},'YYYY-MM-DD hh24:mi:ss'),'hh24:mi:ss') ...
- sprint2(第六天)
昨天休息一天,今天继续做任务. 燃尽图: