zoukankan      html  css  js  c++  java
  • codeforces 455D Serega and Fun

    codeforces 260D Serega and Fun

    题目传送们

    题意:

    给出长度为(n)的序列,要求支持两种操作:
    1.将([l,r])区间的数循环右移一位。
    2.询问([l,r])区间的数中等于(k)的个数。
    一共(q)次操作,要求对于每一个询问进行回答,并且强制在线。
    ((1 leq n,q leq 10^5 , 1 leq a_i leq n))

    题解:

    由于之前写过了(ORZJRY) (I),然后那题里面也有一个循环位移的操作,于是就想到了用块状链表来写这道题目了...(我才不会说我第一个想到的是树套树)对于循环位移的操作,我们是很好处理的,但是对于询问,我们则需要思考一下了。如果用map存的话,每次更新块内信息是(log(n))的,查询也是(log(n))的,如果用数组存下来的话,每次暴力更新块内信息则是(log(n))的,查询则可以做到(O(1)),实际上都不怎么优秀。但仔细想想会发现它的操作实际上只是循环右移一位,所以对于最左边和最右边的两个块,每次位移都只有一个元素会进行更新,所以只需要更新这一个元素即可。然后自己的块状链表写完之后发现并不需要(Split)(Merge)操作了,反而更像一个分块。。不过跑的还挺快,记得根号次位移之后重构一下块防止被卡。

    Code:

    #pragma GCC optimize (2,"inline")
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    bool Finish_read;
    template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
    template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
    template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('
    ');}
    template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
    /*================Header Template==============*/
    #define PAUSE printf("Press Enter key to continue..."); fgetc(stdin);
    #define fi first
    #define se second
    int Blocksz;
    int n,q,c,ans;
    int temp[200650],a[200650];
    /*==================Define Area================*/
    namespace BlockList {
        struct node {
            int tmp[850],cnt[100050];
            int sz,nxt;
        }t[505];
        queue<int>Q;
        void Clear(int o) {t[o].sz=0;}
        void Del(int o) {Q.push(o);Clear(o);}
        int Newnode() {assert(Q.size());int id=Q.front();Q.pop();return id;}
        void Init() {for(int i=1;i<=500;i++) Q.push(i);t[0].nxt=-1,t[0].sz=0;}
        void Debug() {
            int tot=0;
        	for(int i=0;~i;i=t[i].nxt) {
        		printf("sequence %d:",i);
        		for(int j=1;j<=t[i].sz;j++) {
        			printf("%d ",t[i].tmp[j]);
        		}
                tot++;
                printf(" nxt: %d ",t[i].nxt);
        		puts("");
        	}
            puts("");
            cerr<< "totblock:" << tot << endl;
        }
        void Find(int &pos,int &now) {
            for (now=0;t[now].nxt!=-1&&pos>t[now].sz;now=t[now].nxt)
                pos-=t[now].sz;
        }
        void Insert(int *a) {
            int nownd=0;
            for(int i=1;i<=n;i++) {
                if(t[nownd].sz<Blocksz) {
                    ++t[nownd].sz;
                    t[nownd].tmp[t[nownd].sz]=a[i];
                    t[nownd].cnt[a[i]]++;
                }
                else {
                    int nd=Newnode();
                    t[nd].nxt=t[nownd].nxt;
                    t[nownd].nxt=nd;
                    nownd=nd;
                    ++t[nownd].sz;
                    t[nownd].tmp[t[nownd].sz]=a[i];
                    t[nownd].cnt[a[i]]++;
                }
            }
        }
        void Move(int l,int r) {
            int lpos=0,rpos=0;
            Find(l,lpos);Find(r,rpos);
            int Turn=t[rpos].tmp[r];
            if(lpos==rpos) {
                for(int i=r;i>l;i--) {
                    t[lpos].tmp[i]=t[lpos].tmp[i-1];
                }
                t[lpos].tmp[l]=Turn;
                return ;    
            }
            t[rpos].cnt[Turn]--;
            for(int i=r;i<t[rpos].sz;i++) {
                t[rpos].tmp[i]=t[rpos].tmp[i+1];
            }
            t[rpos].sz--;
            t[lpos].sz++;
            for(int i=t[lpos].sz;i>l;i--) {
                t[lpos].tmp[i]=t[lpos].tmp[i-1];
            }
            t[lpos].cnt[Turn]++;
            t[lpos].tmp[l]=Turn;
        }
        int Getcnt(int l,int r,int num) {
        	int lpos=0,rpos=0;
            int res=0;
            Find(l,lpos);Find(r,rpos);
            if(lpos==rpos) {
                for(int i=l;i<=r;i++) {
                    if(t[lpos].tmp[i]==num) {
                        res++;
                    }
                }
                return res;
            }
            for(int i=l;i<=t[lpos].sz;i++) if(t[lpos].tmp[i]==num) res++;
            for(int i=1;i<=r;i++) if(t[rpos].tmp[i]==num) res++;
            for(int i=t[lpos].nxt;i!=rpos;i=t[i].nxt) {
                res+=t[i].cnt[num];
            }
        	return res;
        }
        void Rebuild() {
            int nw=0;
            for(int i=0;~i;i=t[i].nxt) {
                for(int j=1;j<=t[i].sz;j++) {
                    temp[++nw]=t[i].tmp[j];
                    t[i].cnt[t[i].tmp[j]]--;
                }
            }
            for(int i=t[0].nxt;~i;) {
                t[i].sz=0;Q.push(i);
                int now=i;
                i=t[i].nxt;
                t[now].nxt=-1;
            }
            t[0].nxt=-1;t[0].sz=0;
            Insert(temp);
            return ;
        }
    }
      
    using namespace BlockList;
     
    int main() {
        read(n);
        Blocksz=420;
        Init();
        for(int i=1;i<=n;i++) {
            read(a[i]);
        }
        Insert(a);
        read(q);
        while(q--) {
        	int opt;
        	read(opt);
        	if(opt==1) {
        		int l,r;
        		read(l);read(r);
                l=(l+ans-1)%n+1;
                r=(r+ans-1)%n+1;
                if(l>r) swap(l,r);
        		Move(l,r);
                c++;
        	} 
        	if(opt==2) {
        		int l,r,k;
        		read(l);read(r);read(k);
                l=(l+ans-1)%n+1;
                r=(r+ans-1)%n+1;
                k=(k+ans-1)%n+1;
                if(l>r) swap(l,r);
        		ans=Getcnt(l,r,k);
        		printf("%d
    ",ans);
        	} 
            if(c==Blocksz) {
                Rebuild();
                c=0;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java 动态编译
    在ubuntu 18.04下,无线网卡无驱动,连不上wifi,显示wifi没有适配器的解决方法
    由浅入深了解Thrift(1,2,3)
    Docker系列05:docker镜像制作 &Docker file
    Docker系列04:docker数据存储
    Docker系列03:docker网络
    关于在github上 下载源码 clone 非 master 分支的代码
    CentOS 6 & 7 忘记root密码的修改方法
    Windows RDP远程连接CentOS 7
    Windows 上用IntelliJ Idea调试百度大数据分析框架Apache Doris FE
  • 原文地址:https://www.cnblogs.com/Apocrypha/p/9845426.html
Copyright © 2011-2022 走看看