51nod1471 小S的興趣
阿新 • • 發佈:2017-06-26
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的興趣