[51nod 1471]小S的兴趣

题目描述

小S喜欢有趣的事。但是,每个人的兴趣都是独特的。小S热衷于自问自答。有一天,小S想出了一个问题。
有一个包含n个正整数的数组a和针对这个数组的几个问题。这些问题有两种类型:
1. 在数组下标l到r的部分上,将一个单元格循环移动到右端。即以下面方式重新分配数组上的元素。
a[l], a[l+1], …, a[r-1], a[r] → a[r], a[l], a[l+1], …, a[r-1].

  1. 在数组下标l到r的部分上,计算有多少元素的值与k相等。

小S很喜欢这个问题并且很快解决了它,你是否能够解决它呢?

分块

因为不太会做所以打暴力!
分块,每块维护循环链表和桶,各种细节敲起来超麻烦……

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100000+10,B=320;
int cnt[B+5][maxn],size[B+5],fi[B+5],la[B+5],pre[maxn],next[maxn],a[maxn],belong[maxn],b[maxn];
int i,j,k,l,r,t,n,m,tot,top,ans,now,id,x,ca;
bool czy;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
void work(int x){
    int i,t;
    fi[x]=t=b[1];
    la[x]=b[size[x]];
    fo(i,2,size[x]){
        next[t]=b[i];
        pre[b[i]]=t;
        t=b[i];
    }
    pre[b[1]]=0;
    next[b[size[x]]]=0;
}
int main(){
    czy=1;
    n=read();
    fo(i,1,n) a[i]=read();
    fo(i,1,n){
        belong[i]=(i-1)/B+1;
        cnt[belong[i]][a[i]]++;
        size[belong[i]]++;
        if ((i-1)%B==0) fi[belong[i]]=i;
        else{
            next[i-1]=i;
            pre[i]=i-1;
        }
    }
    top=belong[n];
    fo(i,1,n)
        if (i==n||i%B==0) la[belong[i]]=i;
    m=read();
    while (m--){
        t=read();
        if (t==1){
            j=read();k=read();
            if (czy){
                j=(j+ans-1)%n+1;
                k=(k+ans-1)%n+1;
                if (j>k) swap(j,k);
            }
            l=(j-1)/B+1;r=(k-1)/B+1;
            if (l==r){
                t=fi[l];
                fo(i,1,size[l]){
                    b[i]=t;
                    t=next[t];
                }
                j=j-(l-1)*B;k=k-(l-1)*B;
                t=b[k];
                fd(i,k,j+1) b[i]=b[i-1];
                b[j]=t;
                work(l);
                continue;
            }
            k=k-(r-1)*B;
            t=fi[r];
            fo(i,1,size[r]){
                b[i]=t;
                t=next[t];
            }
            id=b[k];
            fd(i,k,2) b[i]=b[i-1];
            b[1]=la[r-1];
            cnt[r][a[id]]--;
            cnt[r][a[b[1]]]++;
            cnt[r-1][a[b[1]]]--;
            next[b[1]]=0;
            la[r-1]=pre[b[1]];
            //pre[b[1]]=0;
            work(r);
            fd(i,r-1,l+1){
                t=la[i-1];
                next[t]=fi[i];
                pre[fi[i]]=t;
                fi[i]=t;
                cnt[i][a[t]]++;
                cnt[i-1][a[t]]--;
                next[pre[t]]=0;
                la[i-1]=pre[t];
                next[pre[t]]=0;
                pre[t]=0; 
            }
            j=j-(l-1)*B;
            t=fi[l];
            fo(i,1,size[l]-1){
                b[i]=t;
                t=next[t];
            }
            fd(i,size[l],j+1) b[i]=b[i-1];
            b[j]=id;
            cnt[l][a[id]]++;
            work(l);
        }
        else{
            ca++;
            if (ca==58){
                t=t;
            }
            j=read();k=read();x=read();
            if (czy){
                j=(j+ans-1)%n+1;
                k=(k+ans-1)%n+1;
                x=(x+ans-1)%n+1;
                if (j>k) swap(j,k);
            }
            ans=0;
            l=(j-1)/B+1;r=(k-1)/B+1;
            if (l==r){
                t=fi[l];
                fo(i,1,size[l]){
                    b[i]=t;
                    t=next[t];
                }
                j=j-(l-1)*B;k=k-(l-1)*B;
                fo(i,j,k)
                    if (a[b[i]]==x) ans++;
                printf("%d\n",ans);
                continue;
            }
            fo(i,l+1,r-1) ans+=cnt[i][x];
            t=fi[l];
            fo(i,1,size[l]){
                b[i]=t;
                t=next[t];
            }
            j=j-(l-1)*B;
            fo(i,j,size[l])
                if (a[b[i]]==x) ans++;
            t=fi[r];
            fo(i,1,size[r]){
                b[i]=t;
                t=next[t];
            }
            k=k-(r-1)*B;
            fo(i,1,k)
                if (a[b[i]]==x) ans++;
            printf("%d\n",ans);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值