外面一定要套一層莫隊的不用說QAQ
學會分析時間複雜度OTZ
按照權值來說,我們需要維護一些數據結構
比如樹狀數組(查詢時二分??) -----O(msqrt(n)logn)
比如分塊(修改O(1)查詢(sqrt(n)))-----O(msqrt(n))
這裏寫了一份分塊。
樹狀數組的話可以按照權值的有無來二分。
#include
#include
#include
#include
#include
#define maxn 200010
using namespace std;
int n, m;
int a[maxn], pos[maxn];
struct opt{
int l, r, id;
bool operator<(const opt& k)const{
if(pos[l] != pos[k.l])return pos[l] < pos[k.l];
return r < k.r;
}
}q[maxn];
int ans[maxn];
struct block{
int sum, cnt, l, r, wy;
int vis[500];
void build(int l, int r){
sum = r - l + 1;
this->l = l, this->r = r;
wy = l - 1;
memset(vis, 0, sizeof vis);
}
void modify(int p, int type){
p -= wy;
if(type == 1){
if(!vis[p])cnt ++;
vis[p] ++;
}
else{
vis[p] --;
if(!vis[p])cnt --;
}
}
bool empty(){return sum == cnt;}
int ask(){
for(int i = 1; i <= sum; i ++)
if(!vis[i])return i + wy;
}
}b[500];
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
int blo = sqrt(n) + 1;
for(int i = 1; i <= blo; i ++){
int L = (i - 1) * blo + 1, R = i * blo;R = min(R, n);
if(i == 1)L = 0;
if(L > R){blo = i;break;}
for(int j = L; j <= R; j ++)
pos[j] = i;
b[i].build(L, R);
}
for(int i = 1; i <= m; i ++){
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
}
sort(q + 1, q + 1 + m);
int l = 1, r = 0;
for(int i = 1; i <= m; i ++){
for(; l < q[i].l; l ++){
if(a[l] > n)continue;
b[pos[a[l]]].modify(a[l], -1);
}
for(; l > q[i].l; l --){
if(a[l - 1] > n)continue;
b[pos[a[l - 1]]].modify(a[l - 1], 1);
}
for(; r < q[i].r; r ++){
if(a[r + 1] > n)continue;
b[pos[a[r + 1]]].modify(a[r + 1], 1);
}
for(; r > q[i].r; r --){
if(a[r] > n)continue;
b[pos[a[r]]].modify(a[r], -1);
}
int ret = 0;
for(int j = 1; j <= blo; j ++)
if(!b[j].empty()){
ret = b[j].ask();
break;
}
ans[q[i].id] = ret;
}
for(int i = 1; i <= m; i ++)
printf("%d\n", ans[i]);
return 0;
}