首页 > 其他分享 >【模板】不删除双指针

【模板】不删除双指针

时间:2024-09-28 21:12:36浏览次数:1  
标签:删除 mid 模板 resl 维护 topb topa 指针

also known as "baka's trick"

目录

版本一

定义一个问题可以双指针,即要找出所有 \(f(l, r)=1\) 的区间,\(f\) 满足 \(f(l, r)\in \{0, 1\}\) 且若 \(f(l, r)=1\) 则 \(f(l_0, r_0)=1\ (l\leq l_0\leq r_0\leq r)\)。一般的做法是维护两个指针 \(l, r\),不断将 \(r\) 右移,将 \(l\) 右移,时刻维护 \(f(i\in[l, r], r)=1\land f(i-1, r)=0\)。这样的复杂度取决于 \(f\) 怎么算。

若 \(f(l, r)\) 依赖于某个 \(g(l, r)\) 的信息,即知道 \(g(l, r)\) 可以唯一确定 \(f(l, r)\),那么可以动态的维护 \(g(l, r)\)(\(l, r\) 是上文的两个指针),算出 \(f\) 判断。注意这里的 \(g\) 的信息需要支持插入删除。

若 \(g\) 不支持删除,但是支持合并,同时信息量较少,我们就引出了不删除双指针。具体做法是额外维护一个 \(mid\in[l, r]\),以及 \(resl[i]=g(i, mid), resr=g(mid+1, r)\)。这样一来 \(g(l, r)=resl[l]+resr\),对于 \(l\) 的右移,在 \(l>mid\) 之前,都可以快速计算 \(g(l, r)\) 从而判断是否需要继续右移。当 \(l>mid\) 的时候,说明此时 \([mid, r]\) 是一个不合法的区间,我们的做法是将 \(mid\) 右推到 \(r\),放弃之前的 \(resl[], resr\) 把他们改成单位元,然后令 \(l=mid\),\(l\) 左移,直到 \([l, r]\) 不合法,在左移的过程中计算 \(resl[l]=g(l, l)+resl[l+1]\)。因为已知原来的 \([mid, r]\) 是不合法区间,所以新的 \(l\) 左移不会超过 \(mid\)。这样一来 \(mid, r\) 只会右移,\(l\) 只会在两个 \(mid\) 断点之间跑一回合,时间复杂度是 \(O(n)\) 次信息合并。

具体算法实现大致如下:

点击查看代码
  static node rel[500010], rer;
  for (int r = 1, l, mid; r < n; ) {
    for (mid = l = r, rel[l + 1] = rer = E; l > 0; --l) {
      rel[l] = merge(I[l], rel[l + 1]);
      if (!rel[l].vaild()) break;
    }
    // [l, r] is invaild or l == 1
    for (++l; ans += r - l + 1, ++r <= n; ) {
      rer = merge(rer, I[r]);
      while (l <= mid && !merge(rel[l], rer).vaild()) ++l;
      if (l > mid) break;
    }
  }

版本二

不删除的双指针,本质上就是要维护一个队列,需要支持 push_back()pop_front() 以及查询全局的某种信息的和,而信息只有结合律,不能作差。以下假设信息合并是 \(O(1)\) 的。

我们回忆,如果不是维护队列而是维护栈,那么我们可以时刻维护栈中所有元素到栈底的信息的和,\(O(1)\) 即可支持所有操作。

考虑用两个栈底相连的栈模拟队列。假设有两个栈 \(A, B\),\(A\) 的栈底连着 \(B\) 的栈底。push_back() 时,往 \(B\) 中 push 元素,并维护 \(B\) 中元素的和。pop_front() 时,如果 \(A\) 栈为空,将 \(B\) 栈的所有元素全部逆序倒进 \(A\) 栈中,重新维护 \(A\) 中所有元素到栈底的信息的和,然后从 \(A\) 中 pop 一个元素,就是将最前的一个元素 pop 掉了。求全局的信息,直接将 \(A\) 栈的信息和与 \(B\) 栈的信息和相加即为全局的答案。

于是我们就完成了这一个队列,剩余部分与普通双指针一样。

点击查看代码
template <class T>
struct qwqUwU {
  T a[410], b[410], suf;
  int topa, topb;
  void clear() {
    topa = topb = 0;
  }
  void push(const T& x) {
    if (topa) suf = suf + x, a[++topa] = x;
    else suf = a[++topa] = x;
  }
  void pop() {
    if (topb) return --topb, void();
    assert(topa);
    swap(topa, topb);
    b[1] = a[topb];
    for (int i = 2; i <= topb; i++) b[i] = a[topb - i + 1] + b[i - 1];
    --topb;
  }
  T sum() {
    if (!topa && !topb) return /*零*/;
    if (!topa) return b[topb];
    if (!topb) return suf;
    return b[topb] + suf;
  }
};

标签:删除,mid,模板,resl,维护,topb,topa,指针
From: https://www.cnblogs.com/caijianhong/p/18438415

相关文章

  • C/C++指针的前世今生
    前言老早之前就想写这个内容了,打了草稿后闲置了两个月,因为其他事就没再动过这个东西了,今天翻草稿箱的时候发现了它,就把它完善出来,顺便我也学习学习。正文指针的前世今生前面先说一下,故事是随便瞎编的。在一个古老的计算机王国里,国王“硬件”统治着所有资源。他拥有广阔......
  • void * 类型指针变量如何赋值
      struct_MyDataType{/*Userdataheader*/UserDataTypeType;OpcUa_UInt16Number;//当前变量在该类型变量的序号/*Protocolinformation*/void*pValue;};typedefstruct_MyDataTypeMyDataType;pRes->Results[i].Value.Value.Doubl......
  • C语言指针plus版
            本篇文章,我们将一起探讨指针高级版一、指针数组、数组指针    1.1指针数组    就是存放指针的数组,因此指针数组是一个数组,不是指针    例如:   int*pa[5];   //整型指针的数组   char*pb[2];  //字符型指针......
  • Day4 C++(运算符重载,模板与容器)(友元函数,运算符重载,赋值运算符,string字符串类,模板)
    1.友元friend1.1概念(掌握)定义:类实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,仅能通过类的成员函数才能读写。如果数据成员定义为公共的,则又破坏了封装性。但是某些情况下,需要频繁读写类的成员,特别是在对某些成员函数多次调用时,由于参数传递、类型检查和安全......
  • 设计模式之模板方法模式
    模板方法模式模板方法模式是一种行为型设计模式,它定义了一个操作中的算法的框架,并将一些步骤的执行延迟到子类中。通过这种方式,模板方法使得子类可以在不改变算法的结构的情况下,重定义算法中的某些特定步骤。核心组成:抽象类(AbstractClass):这个抽象类包含模板方法本身,同时也可......
  • Wincc7.5sp2使用VBA6-全局模板、项目模板和页面模板
    这一篇博客在新浪发表过,那边还在审核,为了避免关闭服务,在这里再次发一遍。那边的博客发表后审核期间,如果想修改是不允许的,审核时间比较长,有点不合理。前面的VBA练习,都是针对具体的项目的具体画面进行编程,在wincc项目还可以全局VBA编程和具体项目VBA编程。我边看技术文档边做练习,......
  • 期刊投稿|Author Agreement模板
    很多期刊要求在投稿的同时,提交AuthorAgreement,但又没给官方模板,AuthorAgreement的作用:AnAuthorAgreementisastatementtocertifythatallauthorshaveseenandapprovedthefinalversionofthemanuscriptbeingsubmitted.Theywarrantthatthearticleisthe......
  • C语言指针系列3——含野指针+assert
    今天我们来继续感受指针的魅力~野指针首先我们来了解一下什么叫野指针~1.定义    野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定......
  • 二级指针内存模型
    二级指针主要分成三种内存模型:1》指针数组:指针指向栈区的一段内存的首地址,并且栈区分配内存空间,每个元素又装有一个指针指向常量区的某一个地址类似于char*myArray[]={"aaaaa","cccccc","bbbbbb","11111"};应用场景名称:指针数组涉及到2个内存区:栈区和栈区 ......
  • pbootcms模板如何调用当前位置面包屑标签
    在PbootCMS中,如果你想在模板中调用当前位置的面包屑导航(Breadcrumb),可以通过特定的标签来实现。以下是具体的实现方法和示例代码:调用面包屑导航标签参数说明separator=*:分隔符,非必填,默认为 >>。indextext=*:首页文本,非必填,默认为“首页”。示例代码假设你希望在模板中......