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的更多相关文章

  1. Serega and Fun CodeForces - 455D (分块 或 splay)

    大意:给定n元素序列, 2种操作 将区间$[l,r]$循环右移1位 询问$[l,r]$中有多少个等于k的元素 现在给定q个操作, 输出操作2的询问结果, 强制在线 思路1: 分块 每个块内维护一个链表 ...

  2. CodeForces 455D 分块

    题目链接:http://codeforces.com/problemset/problem/455/D 题意:给定一个长度为n的序列a[]. m次操作.共有两种操作 1 l r:将序列的a[l].a[ ...

  3. codeforces D. Queue 找规律+递推

    题目链接: http://codeforces.com/problemset/problem/353/D?mobile=true H. Queue time limit per test 1 seco ...

  4. CodeForces - 455D

    Serega loves fun. However, everyone has fun in the unique manner. Serega has fun by solving query pr ...

  5. CodeForces 91B Queue (线段树,区间最值)

    http://codeforces.com/problemset/problem/91/B B. Queue time limit per test: 2 seconds memory limit p ...

  6. codeforces 490B.Queue 解题报告

    题目链接:http://codeforces.com/problemset/problem/490/B 题目意思:给出每个人 i 站在他前面的人的编号 ai 和后面的人的编号 bi.注意,排在第一个位 ...

  7. Codeforces 353D Queue(构造法)

    [题目链接] http://codeforces.com/contest/353/problem/D [题目大意] 10^6个男女排队,每一秒,如果男生在女生前面,即pos[i]是男生,pos[i+1 ...

  8. Codeforces 490B Queue【模拟】

    题意还是很好理解的,根据题目给出描述条件然后求出这串QUEUE 我的做法就是用两个数组 before[] 和 after[] 表示 ai 前面的前面的人的学号 和 ai 后面的后面的人的学号 ex[] ...

  9. CodeForces 91B Queue

    题目链接:http://codeforces.com/contest/91/problem/B 题目大意: 有n头大象排队买票,第i头大象的年龄为ai,如果有比他年轻的大象排在他前面,这头大象就会非常 ...

随机推荐

  1. jquery特效(6)—判断复选框是否选中进行答题提示

    前面有一段时间思想开了小差,跟着师父学习了一段时间才发现差距很大,看来我要奋起直追~\(≧▽≦)/~啦啦啦. 最近公司在做一个项目,需要根据用户选择的选项给出相应的提示,下面来看我写的测试程序的效果: ...

  2. MySQL学习笔记(一)——数据库基础

    自己上大学时也学习过数据库,做开发时也用到过,但是做界面开发对于数据库的使用相对来说是比较简单的,大学时系统学习的数据库也还给老师了,在测试工作中也只是用到了一些基础sql,增删改查这一类的,但是自己 ...

  3. 一个selenium笔试题——去哪网首页获取符合要求的url并保存

    今天在群里看到这样一个笔试题:请使用任何熟悉的面向对象编程语言,编写代码,获取http://www.qyer.com页面中,所有</a>标签"href"属性值包含英文单 ...

  4. legend2---开发日志13(layer_mobile的content传入dom 出现【object object】如何解决)

    legend2---开发日志13(layer_mobile的content传入dom 出现[object object]如何解决) 一.总结 一句话总结: layer_mobile.content只能 ...

  5. Android Studio 使用Gradle多渠道打包

    第一步:配置AndroidManifest.xml 以友盟渠道为例,渠道信息一般都是写在 AndroidManifest.xml文件中,大约如下: <meta-data android:name ...

  6. 【转载】Unity3D的断点调试功能

    原文链接:http://liweizhaolili.blog.163.com/blog/static/162307442013214485190/    断点调试功能可谓是程序员必备的功能了.Unit ...

  7. css3 position:sticky

    最近在写一个小程序,项目中遇到一个需求:页面滚动到tab切换菜单时,菜单fixed到页面顶部: 实现方法: 使用小程序的onPageScroll事件,滚动到指定位置添加fixed样式: bug1:获取 ...

  8. 4 pyspark学习---RDD

    开始新的东西,其实很多操作在第二篇的时候就有所介绍啦.在这里继续学习一遍加深一下印象. 1关于RDD (1) RDD-----Resilient Distributed Dataset,弹性分布式数据 ...

  9. linux中消息队列<一>

    1 概念 (1)链表式结构组织,存放于内核. (2)通过队列标识来引用. (3)通过一个消息类型来索引指定的数据 2 创建消息队列 #include <sys/msg.h> int msg ...

  10. 02-安装JDK - Java快速入门

    jdk安装的版本