CF 455D. Serega and Fun [分块 deque]

Serega and Fun

题意:

[l,r]循环右移一位,查询区间内某个数出现次数


 

为什么好多人用链表?反正我是不会写双向链表

完全可以分块然后模拟啊...中间的块只会插入删除一个元素呀....用deque就好了

虽然说deque常数大但是CF上标准库快啊

不用deque怎么做?可以每个块开一个$O(S)$大小的数组,然后每$S$个操作重建一次

 

一个非常奇怪的事情是$S=n^0.618$比$n^0.5$快了4倍多...300多ms

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <deque>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=350;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int n,Q,op,a[N]; 

int block,pos[N],m;
struct _Blo{int l,r,c[N];}b[M];
deque<int> q[M];
deque<int>::iterator it;
void ini(){
    block=pow(n,0.618);
    m=(n-1)/block+1;
    for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
    for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1, b[i].r=i*block;
    b[m].r=n;
}

struct Block{
    void Set(int x){
        for(int i=b[x].l ; i<=b[x].r ; i++) q[x].push_back(a[i]), b[x].c[a[i]]++;
    }
    void Cha(int l,int r){
        int pl=pos[l],pr=pos[r];
        int f= l-b[pl].l , g= r-b[pr].l , x=q[pr][g];
        if(pl==pr){
            q[pr].erase( q[pr].begin()+g ); q[pl].insert( q[pl].begin()+f , x ); 
        }else{
            q[pl].insert( q[pl].begin()+f , x ); b[pl].c[x]++;
            q[pr].erase( q[pr].begin()+g);       b[pr].c[x]--;

            for(int i=pl;i<pr;i++){
                int x=q[i].back();
                q[i].pop_back();      b[i].c[x]--;
                q[i+1].push_front(x); b[i+1].c[x]++;
            }
        }
    }
    int Que(int l,int r,int k){
        int pl=pos[l],pr=pos[r];
        int f= l-b[pl].l , g= r-b[pr].l;
        int ans=0;
        if(pl==pr){
            for(int i=f ; i<=g ; i++) ans+= q[pl][i]==k;
        }else{
            for(int i=f ; i<(int)q[pl].size() ; i++) ans+= q[pl][i]==k;
            for(int i=0 ; i<=g ; i++) ans+= q[pr][i]==k;
            for(int i=pl+1 ; i<pr ; i++) ans+= b[i].c[k];
        }
        return ans;
    }
}B;
int main(){
    //freopen("in","r",stdin);
    n=read(); ini();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=m;i++) B.Set(i);

    Q=read(); int last=0,l,r;
    while(Q--){
        op=read();
        l=( read()+last-1 )%n+1, r=( read()+last-1 )%n+1; 
        if(l>r) swap(l,r);
        if(op==1) B.Cha(l,r);
        else{
            int k=( read()+last-1 )%n+1;//printf("k %d\n",k);
            last=B.Que(l,r,k); 
            printf("%d\n",last);
        }
    }
}

 

posted @ 2017-03-16 16:47  Candy?  阅读(306)  评论(0编辑  收藏  举报