就找了两三道题,不过回滚莫队思路也好理解,代码实现也不难:
1、我们以块编号为第一关键字排序,右端点位置为第二关键字排序
2、询问时依次枚举区间,我们保留右端点的移量(右边单增),左端点则每次在这一个块中来回移动
3、下一个块时,清空统计答案重做
所以对于每一个块:左端点每次操作√n,右端点总共移n,均摊√n,因此时间复杂度保证了n√n
1)loj#6285
题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及询问区间的最小众数。
输入格式
第一行输入一个数字 n。
第二行输入 n个数字,第 i 个数字为 ai,以空格隔开。
接下来输入 n 行询问,每行输入两个数字 l、r以空格隔开。
表示查询位于[l,r]的数字的众数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 4
1 2
1 4
2 4
3 4
样例输出
1
2
2
2
#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 1e5;
int n,siz,k[N+10],bl[N+10];
struct Que{
int L,r,idx;
}q[N+10];
bool cmp(const Que&A,const Que&B){
return bl[A.L]^bl[B.L]?A.L<B.L:A.r<B.r;
}
inline void init(){
scanf("%d",&n);
Inc(i,1,n)scanf("%d",k+i);
Inc(i,1,n){
int x,y;scanf("%d%d",&x,&y);
q[i]=(Que){x,y,i};
}
siz=sqrt(n);
Inc(i,1,n)bl[i]=(i-1)/siz+1;
sort(q+1,q+1+n,cmp);
}
int rp[N+10];
inline void disc(){
int tmp[N+10];
Inc(i,1,n)tmp[i]=k[i];
sort(tmp+1,tmp+1+n);
int len=unique(tmp+1,tmp+1+n)-tmp-1;
Inc(i,1,n)rp[i]=lower_bound(tmp+1,tmp+1+l