大意:给定n元素序列, 2种操作
- 将区间$[l,r]$循环右移1位
- 询问$[l,r]$中有多少个等于k的元素
现在给定q个操作, 输出操作2的询问结果, 强制在线
思路1: 分块
每个块内维护一个链表, 循环右移相当于删除一个元素, 再插入一个元素, 每个块内再维护一个桶统计元素个数即可
分块好久没写过了, 先放个分块大致流程
void init() { //sqn是分块数, blo[i]是位置i所属块的编号 //L[i], R[i]是位置i所属块的左右边界 sqn = sqrt(n); REP(i,1,n) { blo[i] = (i-1)/sqn+1; L[i] = (blo[i]-1)*sqn+1; R[i] = blo[i]*sqn; } } void work(int l, int r) { REP(i,l,R[l]) { //前半段暴力 } REP(i,blo[l]+1,blo[r]+1) { //处理中间每个块 } if (blo[l]!=blo[r]) { REP(i,L[r],r) { //后半段暴力 } } }