【区间相同数的最小间隔 | 线段树】D. Closest Equals

简介: 笔记

题目描述


15.png


思路

题意: 给定一个数组,多次询问区间 [ l , r ]中相同的数的间隔的最小值。


首先拿到题目第一想法就是考虑,如何维护一个区间相同的数的间距最小值。似乎很熟悉,我们可以用线段树去维护一段区间的最小值信息。那么我们可以开数组 a aa,用来存储不同位置下,和前一位值相同的数的间距。然后我们的线段树就去维护的是数组 a aa,每次查询就返回区间的最小值即可。


但是存在这种情况: 当前询问的区间中,a i 值是最小的,但是 i 这一位对应值,它的前一位相同值并不在区间范围内。也就是说,对于这个询问来说 a i是不能产生贡献的。所以可以将其赋值为一个极大值,这也就需要线段树的单点修改操作。


那么考虑完上面的情况,我们发现如果是这样执行,每次对一个询问区间,我们需要遍历一次区间,把不应该产生贡献的值都给修改掉,并且考虑到当前修改的点,可能对后续的询问产生影响,那么我们还需要在修改回来。这样的时间复杂度是不可以接受的。所以我们实现的过程中,可以将询问进行离线。对询问的区间进行左端点排序。那么在询问完当前区间,在询问下一个区间时,两次询问的左端点之间的数,是不会在有询问的,所以其对后续的询问点的影响需要清空掉。


那么如何清空这些无用点的影响呢?


考虑到这个点对后续的影响是,在询问区间中的点,也就是下一位。所以我们可以开一个 b bb 数组,用于存储每个点它的对应的值的下一位在哪个位置。在修改的时候只需要跳到下一个位置进行修改即可。


代码

struct node {
  int l, r;
  int id;
  bool operator<(const node &A) const {
    if (l == A.l) return r < A.r;
    return l < A.l;
  }
} q[N];
int idx;
int n, m;
map<int, int> mp;
int a[N], b[N];
struct Node {
  int l, r;
  int v;
} tr[N << 2];
#define ls u<<1
#define rs u<<1|1
#define INF 2e9
void pushup(int u) {
  tr[u].v = min(tr[ls].v, tr[rs].v);
}
void build(int u, int l, int r) {
  tr[u] = {l, r};
  if (l == r) { tr[u].v = a[l]; return ; }
  int mid = l + r >> 1;
  build(ls, l, mid), build(rs, mid + 1, r);
  pushup(u);
}
int query(int u, int l, int r) {
  if (tr[u].l >= l && tr[u].r <= r) return tr[u].v;
  int mid = tr[u].l + tr[u].r >> 1;
  int res = INF;
  if (l <= mid) res = min(res, query(ls, l, r));
  if (r > mid) res = min(res, query(rs, l, r));
  return res;
}
void modify(int u, int x) {
  if (tr[u].l >= x && tr[u].r <= x) { tr[u].v = INF; return ; }
  int mid = tr[u].l + tr[u].r >> 1;
  if (x <= mid) modify(ls, x);
  else modify(rs, x);
  pushup(u);
  return ; 
}
int res[N];
// https://codeforces.com/contest/522/problem/D
void solve() {
  cin >> n >> m;
  for (int i = 1; i <= n; i++) a[i] = b[i] = INF;
  for (int i = 1; i <= n; i++) {
    int x; cin >> x;
    if (mp.count(x)) {
      a[i] = i - mp[x];
      b[mp[x]] = i;
    }
    mp[x] = i;
  }
  for (int i = 1; i <= m; i++) {
    int l, r; cin >> l >> r;
    q[i] = {l, r};
    q[i].id = i;
  }
  sort(q + 1, q + 1 + m);
  build(1, 1, n);
  q[m + 1].l = -1;
  for (int i = 1; i <= m; i++) {
    int l = q[i].l, r = q[i].r;
    res[q[i].id] = query(1, l, r);
    for (int p = l; p < q[i + 1].l; p++) {
      if(b[p] <= n) modify(1, b[p]);
    }
  }
  for (int i = 1; i <= m; i++) { 
    if (res[i] >= INF) res[i] = -1;
    cout << res[i] << endl;
  }
}


相关文章
|
JavaScript 安全 开发者
Vue3 中对 TypeScript 的支持
Vue3 中对 TypeScript 的支持
170 2
|
JavaScript
Vue中 Vue.use() 原理及使用
Vue中 Vue.use() 原理及使用
387 0
Vue中 Vue.use() 原理及使用
|
存储 JSON JavaScript
JavaScript深拷贝与浅拷贝
JavaScript深拷贝与浅拷贝
83 0
|
3天前
|
弹性计算 人工智能 安全
云上十五年——「弹性计算十五周年」系列客户故事(第二期)
阿里云弹性计算十五年深耕,以第九代ECS g9i实例引领算力革新。携手海尔三翼鸟、小鹏汽车、微帧科技等企业,实现性能跃升与成本优化,赋能AI、物联网、智能驾驶等前沿场景,共绘云端增长新图景。
|
9天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
8天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
8天前
|
云安全 人工智能 自然语言处理
阿里云x硅基流动:AI安全护栏助力构建可信模型生态
阿里云AI安全护栏:大模型的“智能过滤系统”。