zoukankan      html  css  js  c++  java
  • 51nod1471 小S的兴趣

    题目来源: CodeForces
    基准时间限制:1.5 秒 空间限制:131072 KB 分值: 320

    小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].

     

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

     

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

    Input
    第一行包含整数 n (1 ≤ n ≤ 10*5) —数组元素的数量。第二行包含 n 个整数a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ n)。
    
    第三行包含唯一的整数 q (1 ≤ q ≤ 10*5) —问题的数量。接下来的q行包含了这些询问。
    
    因为你需要在线回答这些问题,所以这些问题将会被编码。第一种类型的询问将会以以下形式给出: 1 Li Ri  。第二种类型的询问将会以以下形式给出: 2 Li Ri Ki 。所有输入的数字都是整数,它们满足以下条件:1 ≤ Li,Ri,Ki ≤ n.
    
    为解码输入的问题,你需要按以下转换操作:
    li = ((Li + lastans - 1) mod n) + 1; 
    ri = ((Ri + lastans - 1) mod n) + 1; 
    ki=((Ki + lastans - 1) mod n) + 1.
    lastans 是到当前询问为止最后一个第二种类型的询问的答案 (初始, lastans = 0)。如果转换后, li 比 ri  大,你需要交换这两个数字。
    Output
    对于每一个第二种类型的问题以单独一行输出答案。
    Input示例
    7
    6 6 2 7 4 2 5
    7
    1 3 6
    2 2 4 2
    2 2 4 7
    2 2 2 5
    1 2 6
    1 1 4
    2 1 7 3
    Output示例
    2
    1
    0
    0

    分块 封装 队列

    安利隔壁sdfzyhx的Splay解法: http://blog.csdn.net/sdfzyhx/article/details/73655923

    这个循环操作看上去很麻烦,很难用数据结构直接维护。

    考虑分块,每块内维护数列和每个数的出现次数,这样每次循环的时候只需要修改首尾两块。

    查询时就暴力统计首尾两块,中间直接查桶即可。

    为了防止循环过多导致块严重变形,每次循环的时候把每个中间整块的尾元素移到下一个整块里,这样每块的大小可以保持不变。

    因为块内操作有点多,写成了封装形式的,看着异常舒心233

    块内用循环队列好像比链表省空间?

    (算错了数组大小,RE了三次)

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 using namespace std;
      7 const int mxn=100005;
      8 const int N=298;
      9 int read(){
     10     int x=0,f=1;char ch=getchar();
     11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     13     return x*f;
     14 }
     15 int n;
     16 struct chain{
     17     int a[503],hd,tl;
     18     int cnt[mxn];
     19     void init(){hd=1;tl=0;return;}
     20     void add_front(int x){
     21         hd=hd-1;if(hd<0)hd=500;
     22         a[hd]=x;
     23         cnt[x]++;
     24         return;
     25     }
     26     void add_back(int x){
     27         tl=tl+1;if(tl>500)tl=0;
     28         a[tl]=x;
     29         cnt[x]++;
     30         return;
     31     }
     32     void del_front(){
     33         cnt[a[hd]]--;
     34         hd=hd+1;if(hd>500)hd=0;
     35         return;
     36     }
     37     void del_back(){
     38         cnt[a[tl]]--;
     39         tl=tl-1;if(tl<0)tl=500;
     40         return;
     41     }
     42     void rotate(int l,int r){
     43 //        printf("rotate:%d %d
    ",l,r);
     44         int st=(hd+l-1)%501,ed=(hd+r-1)%501;
     45 //        printf("st:%d ed:%d
    ",st,ed);
     46         int tmp=a[ed];
     47         while(ed!=st){
     48             a[ed]=(ed==0)?a[500]:a[ed-1];
     49             ed--;if(ed<0)ed=500;
     50         }
     51         a[st]=tmp;
     52         return;
     53     }
     54     int calc(int L,int R,int K){
     55         int st=(hd+L-1)%501,ed=(hd+R-1)%501;
     56         int res=(a[st]==K);
     57         while(st^ed){
     58             st=st+1;if(st>500)st=0;
     59             res+=(a[st]==K);
     60         }
     61         return res;
     62     }
     63     int calc_back(int n,int K){
     64 //        printf("cback:n:%d K:%d
    ",n,K);
     65         int st=tl-n+1;
     66 //        printf("st:%d tl:%d
    ",st,tl);
     67         if(st<0)st+=501;
     68         int res=(a[st]==K);
     69         while(st^tl){
     70             st=st+1;if(st>500)st=0;
     71             if(a[st]==K)res++;
     72         }
     73         return res;
     74     }
     75     int calc_front(int n,int K){
     76         int ed=(hd+n-1)%501;
     77         int st=hd;
     78         int res=(a[st]==K);
     79         while(st^ed){
     80             st=st+1;if(st>500)st=0;
     81             if(a[st]==K)res++;
     82         }
     83         return res;
     84     }
     85     int head(){
     86         return a[hd];
     87     }
     88     int tail(){
     89         return a[tl];
     90     }
     91     void debug(){
     92         printf("debug:
    ");
     93         int x=hd;
     94         printf("%d ",a[hd]);
     95         while(x^tl){
     96             x++;if(x>500)x=0;
     97             printf("%d ",a[x]);
     98         }
     99         puts("");
    100         return;
    101     }
    102 }c[N];
    103 int a[mxn];
    104 int L[N],R[N],sz,block=0;
    105 int bl[mxn];
    106 int lastans=0;
    107 void solve(){
    108     int Q=read(),op,ql,qr;
    109     while(Q--){
    110 //        printf("Q:%d
    ",Q);
    111         op=read();
    112         ql=read();ql=(ql+lastans-1)%n+1;
    113         qr=read();qr=(qr+lastans-1)%n+1;
    114         if(ql>qr)swap(ql,qr);
    115         if(op==1){
    116             if(bl[ql]==bl[qr]){
    117                 c[bl[ql]].rotate(ql-L[bl[ql]]+1,qr-L[bl[ql]]+1);
    118             }
    119             else{
    120                 for(int i=bl[ql]+1;i<bl[qr];i++){
    121                     c[i].add_front(c[i-1].tail());
    122                     c[i-1].del_back();
    123                 }
    124                 c[bl[qr]].add_front(c[bl[qr]-1].tail());
    125                 c[bl[qr]-1].del_back();
    126                 //
    127                 c[bl[qr]].rotate(1,qr-L[bl[qr]]+1+1);
    128                 c[bl[ql]].add_back(c[bl[qr]].head()); 
    129                 //把最后一个元素转到最前面,再加到最前一块的末尾
    130                 c[bl[qr]].del_front();
    131                 c[bl[ql]].rotate(ql-L[bl[ql]]+1,R[bl[ql]]-L[bl[ql]]+1);
    132             }
    133         }
    134         else{
    135             int K=read();K=(K+lastans-1)%n+1;
    136             if(bl[ql]==bl[qr]){
    137                 int res=0;
    138                 res=c[bl[ql]].calc(ql-L[bl[ql]]+1,qr-L[bl[ql]]+1,K);
    139                 printf("%d
    ",res);
    140                 lastans=res;
    141                 continue;
    142             }
    143             int res=0;
    144             for(int i=bl[ql]+1;i<bl[qr];i++){
    145                 res+=c[i].cnt[K];
    146             }
    147 //            c[bl[ql]].debug();
    148 //            c[bl[qr]].debug();
    149             res+=c[bl[ql]].calc_back(R[bl[ql]]-ql+1,K);
    150             res+=c[bl[qr]].calc_front(qr-L[bl[qr]]+1,K);
    151             printf("%d
    ",res);
    152             lastans=res;
    153         }
    154     }
    155     return;
    156 }
    157 int main(){
    158     int i,j;
    159     n=read();
    160     for(i=1;i<=n;i++)a[i]=read();
    161 //    block=min(n,(int)sqrt(n+0.5)+123);
    162     block=400;
    163     sz=(n-1)/block+1;
    164     for(i=1;i<=sz;i++){
    165         L[i]=R[i-1]+1;
    166         R[i]=block*i;
    167         c[i].init();
    168     }
    169     R[sz]=min(R[sz],n);
    170     for(i=1;i<=sz;i++){
    171         for(j=L[i];j<=R[i];j++){
    172             c[i].add_back(a[j]);
    173             bl[j]=i;
    174         }
    175     }
    176     solve();
    177     return 0;
    178 }
  • 相关阅读:
    mysql从一张表查出数据存到另一张表和inner join的用法
    pycharm 看函数列表
    git删除本地所有的更改
    mysql create的几种用法和将字段设为插入时间
    python 装饰器
    pycharm退出unittest模式
    股票基础知识
    linux中查找路径下包含某字符串的所有文件
    SQL distinct用法
    SQL update用法
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7082279.html
Copyright © 2011-2022 走看看