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. nginx启动不了

    nginx简介 Nginx是一个高性能的HTTP和反向代理服务器. 支持的操作系统众多,windows.linux. MacOS X: 可实现负载均衡: Rewrite功能强大: 电商架构大部分都采用 ...

  2. git多人协作冲突解决方法

    http://www.trinea.cn/dev-tools/git-skill/ http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361 ...

  3. STL版 括号匹配(感觉不如之前自己用数组模拟的跑的快)

    数据结构实验之栈四:括号匹配 Time Limit: 1000MS Memory limit: 65536K 题目描述  给你一串字符,不超过50个字符,可能包括括号.数字.字母.标点符号.空格,你的 ...

  4. 简单数位DP

    https://cn.vjudge.net/problem/HDU-4722 懒得写看,代码注释吧;主要存板子 #include <cstdio> #include <cstring ...

  5. js 改变对象的引用地址

    在业务处理中我们经常会碰到列表中有编辑和新增按钮,为了能够提高代码的公用性,我们经常会使用同一组件处理. 这样会出现一个问题就是编辑的时候直接把对象传过去,直接赋值,引用地址是同一个,所以不管修改了那 ...

  6. 如何更快更好的写出cnblog博客?windows live writer推荐

    之前总是会羡慕网上那些技术牛人的博客都写的那么给力,后来一搜发现还是有工具可用的. 这里就推荐一款写博客的"神器",Windows Live Writer (Get It Now! ...

  7. 注销ie中的ActiveX插件

    最新在C#下开发ActiveX控件,遇到一个问题,就是在调试的时候,ActiveX就已经注册在了调试目录下,这样即使安装这个插件,也无法注册到ActiveX的安装目录下.为了解决这个问题,需要注销下调 ...

  8. excel,word,ppt,pdf,swf 文件互相转换

    转自:  http://www.cnblogs.com/wolf-sun/p/3569960.html 引言 之前项目需要,查找了office文档在线预览的解决方案,顺便记录一下,方便以后查询. 方案 ...

  9. python-format函数

    #通过位置 print '{0},{1}'.format('chuhao',20) print '{},{}'.format('chuhao',20) print '{1},{0},{1}'.form ...

  10. 3-1Java程序的执行流程

    3-1Java程序的执行流程 用记事本写一个简单的程序 存到:E:\java路径下 class HelloImooc{    public static void main(String[] agrg ...