51nod1471 小S的兴趣
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\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的兴趣的主要内容,如果未能解决你的问题,请参考以下文章