Serega and Fun Codeforces

https://codeforces.com/problemset/problem/455/D

其实方法很多,然而当初一个也想不到...

1.分块,块内用链表维护

修改[l,r]就当成删除第r个元素,在第l个元素之前插入删掉的元素:就找到r删除,然后调整各个块的结构(对于[block[l]+1,block[r]]中的每个块,把它之前一块的最后一个元素移到自身块的第一个元素),然后找到l应该插入的位置并插入l

修改的同时,维护一下各个块中各个元素出现的次数

查询应该没什么问题了。。。

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 using namespace std;
  6 #define fi first
  7 #define se second
  8 #define mp make_pair
  9 #define pb push_back
 10 typedef long long ll;
 11 typedef unsigned long long ull;
 12 typedef pair<int,int> pii;
 13 const int bs=300;
 14 int cnt;//块数
 15 struct E
 16 {
 17     int pre,nxt;int d;
 18 }e[100100];
 19 int he[355],ta[355];//head,tail
 20 int bl[100100],st[355],ed[355];
 21 int num[355][100100];
 22 void add_tail(int b,int x)
 23 {
 24     if(!ta[b])
 25     {
 26         he[b]=ta[b]=x;
 27     }
 28     else
 29     {
 30         e[ta[b]].nxt=x;e[x].pre=ta[b];
 31         ta[b]=x;
 32     }
 33     ++num[b][e[x].d];
 34 }
 35 int remove_tail(int b)
 36 {
 37     int t=ta[b];
 38     --num[b][e[t].d];
 39     if(he[b]==ta[b])
 40     {
 41         he[b]=ta[b]=0;
 42     }
 43     else
 44     {
 45         ta[b]=e[t].pre;
 46         e[e[t].pre].nxt=0;e[t].pre=0;
 47     }
 48     return t;
 49 }
 50 void add_head(int b,int x)
 51 {
 52     if(!he[b])
 53     {
 54         he[b]=ta[b]=x;
 55     }
 56     else
 57     {
 58         e[he[b]].pre=x;e[x].nxt=he[b];
 59         he[b]=x;
 60     }
 61     ++num[b][e[x].d];
 62 }
 63 void ins_before(int b,int x,int y)//ins x to b before y
 64 {
 65     if(!he[b])
 66     {
 67         he[b]=ta[b]=x;
 68     }
 69     else if(y==he[b])
 70     {
 71         e[y].pre=x;
 72         e[x].nxt=y;
 73         he[b]=x;
 74     }
 75     else if(!y)
 76     {
 77         e[ta[b]].nxt=x;
 78         e[x].pre=ta[b];
 79         ta[b]=x;
 80     }
 81     else
 82     {
 83         e[e[y].pre].nxt=x;
 84         e[x].pre=e[y].pre;
 85         e[y].pre=x;
 86         e[x].nxt=y;
 87     }
 88 }
 89 int qq;
 90 int n,an,lans;
 91 int main()
 92 {
 93     //freopen("/tmp/YALI(10-23)/sample/queue/queue1.in","r",stdin);
 94     //freopen("/tmp/YALI(10-23)/sample/queue/queue1.out","w",stdout);
 95     int i,j,t,l,r,x,nl,nr,nt,b,idx;
 96     scanf("%d",&n);
 97     for(i=1;i<=n;i++)
 98     {
 99         scanf("%d",&t);
100         bl[i]=(i-1)/bs;
101         e[i].d=t;
102     }
103     cnt=(n-1)/bs;
104     for(i=0;i<cnt;i++)
105     {
106         st[i]=bs*i+1;
107         ed[i]=bs*(i+1);
108     }
109     st[cnt]=bs*cnt+1;ed[cnt]=n;
110     for(i=1;i<=n;i++)    add_tail(bl[i],i);
111     scanf("%d",&qq);
112     while(qq--)
113     {
114         scanf("%d",&idx);
115         if(idx==1)
116         {
117             scanf("%d%d",&l,&r);
118             l=(l+lans-1)%n+1;
119             r=(r+lans-1)%n+1;
120             if(l>r)    swap(l,r);
121             /*
122             if(bl[l]==bl[r])
123             {
124                 b=bl[r];
125                 nr=he[b];
126                 for(j=st[b]+1;j<=r;j++)
127                     nr=e[nr].nxt;
128 
129             }
130             else
131             */
132             {
133                 b=bl[r];
134                 nr=he[b];
135                 for(j=st[b]+1;j<=r;j++)
136                     nr=e[nr].nxt;
137                 if(nr==he[b])    he[b]=e[nr].nxt;
138                 else    e[e[nr].pre].nxt=e[nr].nxt;
139                 if(nr==ta[b])    ta[b]=e[nr].pre;
140                 else    e[e[nr].nxt].pre=e[nr].pre;
141                 e[nr].pre=e[nr].nxt=0;
142                 --num[b][e[nr].d];
143                 b=bl[l];
144                 for(j=bl[r];j>b;j--)
145                 {
146                     nt=remove_tail(j-1);
147                     add_head(j,nt);
148                 }
149                 if(l==ed[b])
150                 {
151                     nl=0;
152                 }
153                 else
154                 {
155                     nl=ta[b];
156                     for(j=ed[b]-2;j>=l;j--)
157                         nl=e[nl].pre;
158                 }
159                 ins_before(b,nr,nl);
160                 ++num[b][e[nr].d];
161             }
162         }
163         else
164         {
165             scanf("%d%d%d",&l,&r,&x);
166             l=(l+lans-1)%n+1;
167             r=(r+lans-1)%n+1;
168             x=(x+lans-1)%n+1;
169             if(l>r)    swap(l,r);
170             an=0;
171             if(bl[l]==bl[r])
172             {
173                 b=bl[l];
174                 nl=he[b];
175                 for(j=st[b]+1;j<=l;j++)
176                     nl=e[nl].nxt;
177                 for(j=l;j<=r;j++)
178                 {
179                     an+=(e[nl].d==x);
180                     nl=e[nl].nxt;
181                 }
182             }
183             else
184             {
185                 for(j=bl[l]+1;j<=bl[r]-1;j++)
186                     an+=num[j][x];
187                 b=bl[r];
188                 nr=he[b];
189                 an+=(e[nr].d==x);
190                 for(j=st[b]+1;j<=r;j++)
191                 {
192                     nr=e[nr].nxt;
193                     an+=(e[nr].d==x);
194                 }
195                 b=bl[l];
196                 nl=ta[b];
197                 an+=(e[nl].d==x);
198                 for(j=ed[b]-1;j>=l;j--)
199                 {
200                     nl=e[nl].pre;
201                     an+=(e[nl].d==x);
202                 }
203             }
204             lans=an;
205             printf("%d
",an);
206         }
207     }
208     return 0;
209 }
View Code

2.分块,定期重构(官方题解

跟方法1大部分一样,但是块内不用链表,直接用vector或者数组,插入/删除就暴力,同时维护各个块中各个元素出现次数,然后每sqrt(n)次重构所有块

3.平衡树(见官方题解下面的第一条评论)

(额外解释:为什么是n*log^2而不是n*log呢?因为所有的下标都是动态的。询问(l,r,k)时,需要在k-splay中找出有多少个点下标在[l,r]内,而每一次查询下标必须要在0-splay中查询一下(注意下标是动态的,不能直接记下下标))


http://210.33.19.103/contest/1025/problem/3

此题同C.queue

原文地址:https://www.cnblogs.com/hehe54321/p/9838762.html