1. 程式人生 > >51nod1471 小S的興趣

51nod1471 小S的興趣

tex 防止 csdn pla using put deb tput calc

題目來源: 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\n",l,r);
 44         int st=(hd+l-1)%501,ed=(hd+r-1)%501;
 45 //        printf("st:%d ed:%d\n",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",n,K);
 65         int st=tl-n+1;
 66 //        printf("st:%d tl:%d\n",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:\n");
 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\n",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\n",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\n",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 }

51nod1471 小S的興趣