您的位置:首页 > 其它

[置顶] CodeForces 455D Serega and Fun (分块+双端队列)

2016-10-12 11:35 411 查看
题意:给出一个序列,两种操作

1.将区间[l,r]滚动一次

2.询问区间[l,r]中值等于k的数有多少个

在线

分块之后,两种操作都能在sqrt(n)的复杂度内解决,将每个块都设置为队列,这样滚动起来非常方便

一开始没有看到数值的范围,直接用的分块+bitset+双端队列,结果T了,后来看到了这一点,想写个分块+循环队列,结果发现编程复杂度太高..(好菜)…最终还是分块+双端队列…

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>

using namespace std;

#define maxn 100005

int n,m;
int b[350][maxn];
deque<int>que[350];
int val[maxn];
int block,num,belong[maxn],l[maxn],r[maxn];

void init()
{
block=sqrt(n);
num=n/block;
if(n&block) num++;
for(int i=1; i<=n; i++)
{
belong[i]=(i-1)/block+1;
}
for(int i=1; i<=num; i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}
r[num]=n;
for(int i=1; i<=num; i++)
{
for(int j=l[i]; j<=r[i]; j++)
{
b[i][val[j]]++;
que[i].push_back(val[j]);
}
}
}

void update(int x,int y)
{
if(belong[x]==belong[y])
{
int index=belong[x];
x-=l[index];
y-=l[index];
int temp=que[index][y];
for(int i=y; i>x; i--)
{
que[index][i]=que[index][i-1];
}
que[index][x]=temp;
return ;
}
int temp=que[belong[y]][y-l[belong[y]]];
int temp2=que[belong[x]][r[belong[x]]-l[belong[x]]];
b[belong[x]][temp2]--;
b[belong[y]][temp]--;
for(int i=r[belong[x]]; i>x; i--)
{
que[belong[x]][i-l[belong[x]]]=que[belong[x]][i-l[belong[x]]-1];
}
que[belong[x]][x-l[belong[x]]]=temp;
b[belong[x]][temp]++;
for(int i=belong[x]+1; i<belong[y]; i++)
{
int tp=temp2;
b[i][temp2]++;
temp2=que[i][r[i]-l[i]];
que[i].pop_back();
que[i].push_front(tp);
b[i][temp2]--;
}
for(int i=y; i>l[belong[y]]; i--)
{
que[belong[y]][i-l[belong[y]]]=que[belong[y]][i-l[belong[y]]-1];
}
que[belong[y]][0]=temp2;
b[belong[y]][temp2]++;
}

int query(int x,int y,int k)
{
int ans=0;
if(belong[x]==belong[y])
{
for(int i=x; i<=y; i++)
{
if(que[belong[x]][i-l[belong[x]]]==k) ans++;
}
return ans;
}
for(int i=x; i<=r[belong[x]]; i++)
{
if(que[belong[x]][i-l[belong[x]]]==k) ans++;
}
for(int i=belong[x]+1; i<belong[y]; i++)
{
ans+=b[i][k];
}
for(int i=l[belong[y]]; i<=y; i++)
{
if(que[belong[y]][i-l[belong[y]]]==k) ans++;
}
return ans;
}

int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&val[i]);
}
init();
scanf("%d",&m);
int ans=0;
while(m--)
{
int op;
scanf("%d",&op);
int x,y;
scanf("%d%d",&x,&y);
x=(x+ans-1)%n+1;
y=(y+ans-1)%n+1;
if(x>y) swap(x,y);
if(op==1)
{
update(x,y);
}
else if(op==2)
{
int k;
scanf("%d",&k);
k=(k+ans-1)%n+1;
printf("%d\n",ans=query(x,y,k));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: