• 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
    ",k);
                last=B.Que(l,r,k); 
                printf("%d
    ",last);
            }
        }
    }
  • 相关阅读:
    求循环小数
    Android中Intent的用法总结
    Java中@Override的作用
    三种继承方式和访问控制方式对子类成员的影响
    设计一个用于人事管理的People(人员)类
    QSort函数对不同类型数据快速排序浅谈
    QSQLITE 使用
    c++控制内存分配
    dll加载过程全局变量会先初始化
    二维数组
  • 原文地址:https://www.cnblogs.com/candy99/p/6560310.html
Copyright © 2020-2023  润新知