【CodeForces】455D Serega and Fun 双向链表分块暴力
来源:互联网 发布:linux exe 用什么命令 编辑:程序博客网 时间:2024/06/05 16:12
传送门:【CodeForces】455D Serega and Fun
题目分析:
看大神各种splay高效过之。。。实在无力啊。。。只会分块暴力搞了。。。
具体思路是这样的:
首先我们将整个数组用双向链表模拟,对于所有元素x,设L[x]为他实际上左边的元素,R[x]为他实际上右边的元素,然后将其分块,分块系数自己定。。设H[x]指向第x块开头的元素。
由于CF能开大数组的特性。。我们直接开块数*数组长度的二维大数组保存该块中某个元素的个数。
每次操作,我们先确定l和r所在的块,然后确定l和r在各自对应的块中相对于块中头元素的位移,然后暴力推出该位置对应的元素。设l位置上的元素为 ll ,r上的元素为 rr 。
对于操作一,如果l == r则直接不执行(我的可能会出一点问题,解决比较繁琐还不如直接特判)。设 ll 所在的块编号为pos_l, rr 所在的块编号为pos_r,将所有pos_l+1到pos_r的H[ i ]指向L[H[ i ]],即将 l 到 r 内所有的元素右移一位,也可以理解为将整个需要变动的块左移一位,然后执行删除元素 rr 的操作,再然后将其插入到 ll 的左边,并且如果 ll 正好是某个块的头元素,那么将该块的H[ ]指向rr。不要忘记修改元素在对应块中的计数!
对于操作二,暴力统计 ll 所在区间内k的个数以及 rr所在区间内k的个数(因为我们每个块保存的是整个块内k的个数,不能直接得到这个块内部分区间内k的个数),对于夹在中间的块,直接加上该块内k的个数即可。
分块题我觉得精髓在于调整分块系数。。。本题如果用n^0.5作为系数则能勉强过掉。。但是如果用n^0.618可以不到1000ms就搞定。。。
双向链表(双端队列)+分块,队友提了一下,很不错的想法!然后我们各自实现了一个,他是STL,我是自己模拟双向链表,STL跑的比直接模拟的要快,应该是STL里面有什么效率比较好的元素吧。。写了将近半天,能过掉真的很开心啊,不过话说一开始map直接TLE了。。。果然在CF平台上还是大数组靠谱。。
代码如下:
#include <map>#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )#define CLR( a , x ) memset ( a , x , sizeof a )const int SQR = 330 ;const int MAXN = 100005 ;int cnt[SQR][MAXN] ;int L[MAXN] , R[MAXN] , H[SQR] ;int a[MAXN] ;int sqr ;int last_ans ;int n , m ;void solve () {int ch , l , r , k , x ;last_ans = 0 ;sqr = pow ( n , 0.618 ) ;//CLR ( cnt , 0 ) ;FOR ( i , 1 , n ) {scanf ( "%d" , &a[i] ) ;++ cnt[( i - 1 ) / sqr][a[i]] ;L[i] = i - 1 ;R[i] = i + 1 ;}L[1] = R[n] = -1 ;FOR ( i , 0 , n / sqr ) H[i] = i * sqr + 1 ;scanf ( "%d" , &m ) ;REP ( _ , 0 , m ) {scanf ( "%d%d%d" , &ch , &l , &r ) ;l = ( l + last_ans - 1 ) % n + 1 ;r = ( r + last_ans - 1 ) % n + 1 ;if ( l > r ) swap ( l , r ) ;if ( ch == 1 && l == r ) continue ;int pos_l = ( l - 1 ) / sqr ;//l所在的块int pos_r = ( r - 1 ) / sqr ;//r所在的块int ll = H[pos_l] ;//l所在的块的头元素int rr = H[pos_r] ;//r所在的块的头元素l -= pos_l * sqr ;//l相对于所在块头元素的位移r -= pos_r * sqr ;//r相对于所在块头元素的位移REP ( i , 1 , l ) ll = R[ll] ;//找到l所在的位置对应的元素REP ( i , 1 , r ) rr = R[rr] ;//找到r所在的位置对应的元素if ( ch == 1 ) {-- cnt[pos_r][a[rr]] ;//将元素rr从所在块删除++ cnt[pos_l][a[rr]] ;//将元素rr添加到ll所在的块if ( ll == H[pos_l] ) H[pos_l] = rr ;//如果ll正好是块头,那么该块的头部指针指向rrREV ( i , pos_r , pos_l + 1 ) {H[i] = L[H[i]] ;//将该块的左边块的最右端的元素添加到该块-- cnt[i - 1][a[H[i]]] ;//将该块左端的最右端的元素从左端删除++ cnt[i][a[H[i]]] ;//将该块左端的最右端的元素添加到该块的左端开头}//将rr从pos_r中删除R[L[rr]] = R[rr] ;L[R[rr]] = L[rr] ;//将rr添加到ll的左边L[rr] = L[ll] ;R[rr] = ll ;R[L[ll]] = rr ;L[ll] = rr ;/*for ( int i = H[0] ; ~i ; i = R[i] )printf ( "%d-" , a[i] ) ;printf ( "\n" ) ;for ( int i = 0 ; i <= sqr ; ++ i )printf ( "H[%d] = %d : %d\n" , i , H[i] , a[H[i]] ) ;*/} else {scanf ( "%d" , &k ) ;k = ( k + last_ans - 1 ) % n + 1 ;int ans = 0 ;if ( pos_l == pos_r ) {for ( int i = ll ; i != R[rr] ; i = R[i] ) if ( a[i] == k ) ans ++ ;} else {for ( int i = L[H[pos_l + 1]] ; i != L[ll] ; i = L[i] ) if ( a[i] == k ) ans ++ ;for ( int i = H[pos_r] ; i != R[rr] ; i = R[i] ) if ( a[i] == k ) ans ++ ;REP ( i , pos_l + 1 , pos_r ) ans += cnt[i][k] ;}printf ( "%d\n" , ans ) ;last_ans = ans ;}}}int main () {while ( ~scanf ( "%d" , &n ) )solve () ;return 0 ;}
- 【CodeForces】455D Serega and Fun 双向链表分块暴力
- codeforces 455 D. Serega and Fun (分块+双向链表)
- 【分块】 codeforces 455D - Serega and Fun
- [Codeforces 455D] Serega and Fun (分块)
- [Codeforces455D]Serega and Fun(分块+双向链表)
- CodeForces 455D Serega and Fun (分块+双端队列)
- Codeforces 455D Serega and Fun【解法一】
- Codeforces 455D Serega and Fun【解法二】
- codeforces 455D 分块
- Codeforces#86D Powerful array(分块暴力)
- codeforces #308 D.Vanya and Triangles(枚举+斜率分块)
- codeforces 375D. Tree and Queries (莫队+分块)
- Codeforces Round #305 (Div. 2)-Mike and Fun(暴力求解连续1)
- Codeforces 394D Physical Education and Buns(暴力)
- Codeforces 6D Lizards and Basements 2 dfs+暴力
- Codeforces 335D Rectangles and Square 暴力 + DP
- Codeforces 367D Sereja and Sets 位运算暴力
- CodeForces 552D — Vanya and Triangles 暴力枚举
- 快速幂
- OSX架构概述
- 稀疏数组(Sparse array)
- 非零点之间聚类
- oralce11g 注册表卸载20140810
- 【CodeForces】455D Serega and Fun 双向链表分块暴力
- 编辑器
- UVA - 253 Cube painting
- 【嵌入式Linux】[串口]:串口打印时,文件系统中的中文内容乱码,U盘中文内容乱码
- hdu 1166 敌兵布阵(单点更新及区间求和)
- 【Leetcode长征系列】Symmetric Tree
- java CyclicBarrier使用
- 存专题的新博客
- iOS绘图