Serega and Fun Codeforces - 455D || queue
https://codeforces.com/problemset/problem/455/D
其实方法很多,然而当初一个也想不到...
1.分块,块内用链表维护
修改[l,r]就当成删除第r个元素,在第l个元素之前插入删掉的元素:就找到r删除,然后调整各个块的结构(对于[block[l]+1,block[r]]中的每个块,把它之前一块的最后一个元素移到自身块的第一个元素),然后找到l应该插入的位置并插入l
修改的同时,维护一下各个块中各个元素出现的次数
查询应该没什么问题了。。。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int bs=;
int cnt;//块数
struct E
{
int pre,nxt;int d;
}e[];
int he[],ta[];//head,tail
int bl[],st[],ed[];
int num[][];
void add_tail(int b,int x)
{
if(!ta[b])
{
he[b]=ta[b]=x;
}
else
{
e[ta[b]].nxt=x;e[x].pre=ta[b];
ta[b]=x;
}
++num[b][e[x].d];
}
int remove_tail(int b)
{
int t=ta[b];
--num[b][e[t].d];
if(he[b]==ta[b])
{
he[b]=ta[b]=;
}
else
{
ta[b]=e[t].pre;
e[e[t].pre].nxt=;e[t].pre=;
}
return t;
}
void add_head(int b,int x)
{
if(!he[b])
{
he[b]=ta[b]=x;
}
else
{
e[he[b]].pre=x;e[x].nxt=he[b];
he[b]=x;
}
++num[b][e[x].d];
}
void ins_before(int b,int x,int y)//ins x to b before y
{
if(!he[b])
{
he[b]=ta[b]=x;
}
else if(y==he[b])
{
e[y].pre=x;
e[x].nxt=y;
he[b]=x;
}
else if(!y)
{
e[ta[b]].nxt=x;
e[x].pre=ta[b];
ta[b]=x;
}
else
{
e[e[y].pre].nxt=x;
e[x].pre=e[y].pre;
e[y].pre=x;
e[x].nxt=y;
}
}
int qq;
int n,an,lans;
int main()
{
//freopen("/tmp/YALI(10-23)/sample/queue/queue1.in","r",stdin);
//freopen("/tmp/YALI(10-23)/sample/queue/queue1.out","w",stdout);
int i,j,t,l,r,x,nl,nr,nt,b,idx;
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d",&t);
bl[i]=(i-)/bs;
e[i].d=t;
}
cnt=(n-)/bs;
for(i=;i<cnt;i++)
{
st[i]=bs*i+;
ed[i]=bs*(i+);
}
st[cnt]=bs*cnt+;ed[cnt]=n;
for(i=;i<=n;i++) add_tail(bl[i],i);
scanf("%d",&qq);
while(qq--)
{
scanf("%d",&idx);
if(idx==)
{
scanf("%d%d",&l,&r);
l=(l+lans-)%n+;
r=(r+lans-)%n+;
if(l>r) swap(l,r);
/*
if(bl[l]==bl[r])
{
b=bl[r];
nr=he[b];
for(j=st[b]+1;j<=r;j++)
nr=e[nr].nxt; }
else
*/
{
b=bl[r];
nr=he[b];
for(j=st[b]+;j<=r;j++)
nr=e[nr].nxt;
if(nr==he[b]) he[b]=e[nr].nxt;
else e[e[nr].pre].nxt=e[nr].nxt;
if(nr==ta[b]) ta[b]=e[nr].pre;
else e[e[nr].nxt].pre=e[nr].pre;
e[nr].pre=e[nr].nxt=;
--num[b][e[nr].d];
b=bl[l];
for(j=bl[r];j>b;j--)
{
nt=remove_tail(j-);
add_head(j,nt);
}
if(l==ed[b])
{
nl=;
}
else
{
nl=ta[b];
for(j=ed[b]-;j>=l;j--)
nl=e[nl].pre;
}
ins_before(b,nr,nl);
++num[b][e[nr].d];
}
}
else
{
scanf("%d%d%d",&l,&r,&x);
l=(l+lans-)%n+;
r=(r+lans-)%n+;
x=(x+lans-)%n+;
if(l>r) swap(l,r);
an=;
if(bl[l]==bl[r])
{
b=bl[l];
nl=he[b];
for(j=st[b]+;j<=l;j++)
nl=e[nl].nxt;
for(j=l;j<=r;j++)
{
an+=(e[nl].d==x);
nl=e[nl].nxt;
}
}
else
{
for(j=bl[l]+;j<=bl[r]-;j++)
an+=num[j][x];
b=bl[r];
nr=he[b];
an+=(e[nr].d==x);
for(j=st[b]+;j<=r;j++)
{
nr=e[nr].nxt;
an+=(e[nr].d==x);
}
b=bl[l];
nl=ta[b];
an+=(e[nl].d==x);
for(j=ed[b]-;j>=l;j--)
{
nl=e[nl].pre;
an+=(e[nl].d==x);
}
}
lans=an;
printf("%d\n",an);
}
}
return ;
}
2.分块,定期重构(官方题解)
跟方法1大部分一样,但是块内不用链表,直接用vector或者数组,插入/删除就暴力,同时维护各个块中各个元素出现次数,然后每sqrt(n)次重构所有块
3.平衡树(见官方题解下面的第一条评论)
(额外解释:为什么是n*log^2而不是n*log呢?因为所有的下标都是动态的。询问(l,r,k)时,需要在k-splay中找出有多少个点下标在[l,r]内,而每一次查询下标必须要在0-splay中查询一下(注意下标是动态的,不能直接记下下标))
http://210.33.19.103/contest/1025/problem/3
此题同C.queue
Serega and Fun Codeforces - 455D || queue的更多相关文章
- Serega and Fun CodeForces - 455D (分块 或 splay)
大意:给定n元素序列, 2种操作 将区间$[l,r]$循环右移1位 询问$[l,r]$中有多少个等于k的元素 现在给定q个操作, 输出操作2的询问结果, 强制在线 思路1: 分块 每个块内维护一个链表 ...
- CodeForces 455D 分块
题目链接:http://codeforces.com/problemset/problem/455/D 题意:给定一个长度为n的序列a[]. m次操作.共有两种操作 1 l r:将序列的a[l].a[ ...
- codeforces D. Queue 找规律+递推
题目链接: http://codeforces.com/problemset/problem/353/D?mobile=true H. Queue time limit per test 1 seco ...
- CodeForces - 455D
Serega loves fun. However, everyone has fun in the unique manner. Serega has fun by solving query pr ...
- CodeForces 91B Queue (线段树,区间最值)
http://codeforces.com/problemset/problem/91/B B. Queue time limit per test: 2 seconds memory limit p ...
- codeforces 490B.Queue 解题报告
题目链接:http://codeforces.com/problemset/problem/490/B 题目意思:给出每个人 i 站在他前面的人的编号 ai 和后面的人的编号 bi.注意,排在第一个位 ...
- Codeforces 353D Queue(构造法)
[题目链接] http://codeforces.com/contest/353/problem/D [题目大意] 10^6个男女排队,每一秒,如果男生在女生前面,即pos[i]是男生,pos[i+1 ...
- Codeforces 490B Queue【模拟】
题意还是很好理解的,根据题目给出描述条件然后求出这串QUEUE 我的做法就是用两个数组 before[] 和 after[] 表示 ai 前面的前面的人的学号 和 ai 后面的后面的人的学号 ex[] ...
- CodeForces 91B Queue
题目链接:http://codeforces.com/contest/91/problem/B 题目大意: 有n头大象排队买票,第i头大象的年龄为ai,如果有比他年轻的大象排在他前面,这头大象就会非常 ...
随机推荐
- 盒子的display属性
<body> <div style="display:inline">Box-1</div> <div style="displ ...
- nginx启动不了
nginx简介 Nginx是一个高性能的HTTP和反向代理服务器. 支持的操作系统众多,windows.linux. MacOS X: 可实现负载均衡: Rewrite功能强大: 电商架构大部分都采用 ...
- Vue实例和方法
github地址:https://github.com/manlili/vue_learn里面的lesson03 一 实例 每个 Vue 实例都会代理其 data 对象里所有的属性,改变data,vu ...
- 关于Linux启动文件rc.local的解惑
背景 首先,rc.local是Linux启动程序在login程序前执行的最后一个脚本,有的服务器中在rc.local中可能会有一句touch /var/lock/subsys/local,这是干什么的 ...
- 在Linux中利用Service命令添加系统服务及开机自启动
有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务 主要用三种方式进行这一操作: ln -s 在/etc/rc.d/rc*.d目录中建立/e ...
- __FILE__,__LINE__,__func__ 真好用,DEBUG利器啊!
我是不喜欢用类似VC下的F5,F10.曾经很喜欢用.被代码逻辑逼的没招了.所以不喜欢用了. 比如,错误是根据动态数据,产生的行为错误,无论是该写的未写,还是不该写的写了.指针跑飞什么等等,无非就是上述 ...
- double转int时精度不一致问题
float和double类型的主要设计目的是为了科学计算和工程计算.它们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果,所以不应该 ...
- ACM2016级新生第三周训练赛
本次是弱校题解-比赛链接 备用链接 题目还是比较基础,比较简单.认真补题,学会学习. A -人见人爱A^B 题解: 求 A的B次方,我们可以用循环进行累乘操作,进而计算出次方.因为题目要求只需要求出最 ...
- TypeScript完全解读(26课时)_7.ES6精讲 - 类Class基础
ES6精讲 - 类Class基础 es5中创建构造函数和实例 原来在es5中的写法 定义好Point后,在原型对象上定义getPostion的方法 实例自身是没有这个方法的,我们调用的时候会去创建他的 ...
- C#基础:线程之异步委托
线程:是程序中独立的指令流.在我们熟悉的Visual Studio编辑器中输入C# 代码的时候,系统会自动分析代码,提示你输入的代码出现的各种错误,这是一个后台线程完成的. 创建线程的一种简单的方式就 ...