CF940F Machine Learning

Problem

给出 数组 (a{})

(q)次操作

1、查询区间(l) ~ (r) 中每个数字出现次数(mex)
2、单点修改。

出现次数的mex 注意不是数值的 mex

(1 leq a_i leq 10^9)

考虑离散化 因为数字较大 (map) 自带 (log) 和 大常数。。
然后用带修莫队维护的复杂度就会变成 (n^{5/3}* log n)
显然是跑不过去的。。

离散化有一个问题 就是你要把询问中的修改的数值也离散化

然后 用一个 (cntt_i) 记录 (i) 出现的次数 (tot_i) 记录出现 (i) 次的个数

带修莫队有一个时间戳 排序应该是按 (l)所在的块 -> (r)所在的块 -> 当前修改的时间戳。。

带修莫队的块大小应该是 (n^{2/3})

对于这道题还有一个不太严谨的结论:求(mex)的复杂度每次扫一遍不会超过 (sqrt n)

(nsqrt n le n^{5/3})

#include<bits/stdc++.h>
using namespace std ;
int n , Q ;
vector < int > v , b ;
const int N = 2e5 + 10 ;
int bl[N] ;
struct node { int l , r , id , t ; } q[N] ;
struct change { int x , val ; } c[N] ;
int tot[N] , cntt[N] ;
inline void add(int x) {
  -- tot[cntt[x]] ;
  ++ tot[++ cntt[x]] ;
}
inline void del(int x) {
  -- tot[cntt[x]] ;
  ++ tot[-- cntt[x]] ;
}
inline void modify(int now , int i) {
  if(q[i].l <= c[now].x && c[now].x <= q[i].r) {
    del(v[c[now].x]) ;
    add(c[now].val) ;
  } swap(v[c[now].x] , c[now].val) ;
}
int ans[N] ;
signed main() {
  ios :: sync_with_stdio(false) ;
  cin.tie(nullptr) ; cout.tie(nullptr) ;
  cin >> n >> Q ; int unt = pow(n , 2.0 / 3.0) ;
  for(register int i = 0 ; i < n ; i ++) { int x ; cin >> x ; v.push_back(x) ; }
  for(register int i = 0 ; i < n ; i ++) { b.push_back(v[i]) ; bl[i] = (i - 1) / unt + 1 ; }
  int cnt , cnt2 ; cnt = cnt2 = 0 ;
  for(register int i = 0 ; i < Q ; i ++) { int opt , x , y ; cin >> opt >> x >> y ;
    if(opt == 1) { ++ cnt ; q[cnt] = {-- x , -- y , cnt , cnt2} ; }
    if(opt == 2) { ++ cnt2 ; c[cnt2] = { -- x , y } ; b.push_back(y) ; }
  }
  sort(b.begin() , b.end()) ; b.erase(unique(b.begin() , b.end()) , b.end()) ;
  for ( int & x : v ) x = lower_bound(b.begin() , b.end() , x) - b.begin() ;
  for(register int i = 1 ; i <= cnt2 ; i ++) { c[i].val = lower_bound(b.begin() , b.end() , c[i].val) - b.begin() ; }
  sort(q + 1 , q + cnt + 1 , [] (node x , node y) {
    if(bl[x.l] ^ bl[y.l]) return x.l < y.l ;
    if(bl[x.r] ^ bl[y.r]) return x.r < y.r ;
    return x.t < y.t ;
  }) ;
  int l = 1 , r = 0 , now = 0 ;
  for(register int i = 1 ; i <= cnt ; i ++) {
    while(l > q[i].l) add(v[-- l]) ;
    while(r < q[i].r) add(v[++ r]) ;
    while(l < q[i].l) del(v[l ++]) ;
    while(r > q[i].r) del(v[r --]) ;
    while(now < q[i].t) modify(++ now , i) ;
    while(now > q[i].t) modify(now -- , i) ;
    for(ans[q[i].id] = 1 ; tot[ans[q[i].id]] > 0 ; ++ ans[q[i].id]) ;
  } for(register int i = 1 ; i <= cnt ; i ++) cout << ans[i] << '
' ;
  return 0 ;
}
原文地址:https://www.cnblogs.com/Isaunoya/p/11763446.html