首页 > 其他分享 >CF1514D-区间(绝对)众数-莫队、随机化、可持久化线段树

CF1514D-区间(绝对)众数-莫队、随机化、可持久化线段树

时间:2024-03-18 19:00:47浏览次数:30  
标签:CF1514D int tr 绝对 pos 随机化 ls 众数

link:https://codeforces.com/contest/1514/problem/D
很久以前小号打的场了,当时D题写的莫队,现在重新来看看。
题意:给一个序列 \([a_1,\dots,a_n]\),有q次询问,每次问:把\([a_l,\dots,a_r]\) 划分最少几个不相交子序列,才能使得每个子序列是beautiful的。称一个序列 \(a_1,\dots,a_x\) 是beautiful的,当且仅当其不存在某个元素的出现次数超过\(\lceil x/2\rceil\)
\(1\leq n,q\leq 3\times 10^5\).


如果某个子区间不存在绝对众数,答案是1,否则假设绝对众数 \(x\) 出现了 \(cnt_x\) 次,则一定要把一些 \(x\) 单独拿出来作为一个序列,假设要拿出来 \(y\) 个,则需要有 \(cnt_x-y\leq (len-cnt_x)+1\),得\(y\geq 2cnt_x -len -1\),此时答案是 \(1+\max(0,2 cnt_x-len-1)\).

所有问题都指向,1、判断区间是否存在绝对众数。2、确定绝对众数的出现次数。后者容易回答,因为绝对众数要么唯一,要么两个出现次数一样,找到某个绝对众数 \(v\) 后,容易通过前缀和 \(O(\log n)\) 地找到。
而如何寻找绝对众数呢?

  • 莫队典中典问题,维护每个值 \(v\) 的出现次数、以及出现次数为 \(c\) 的值有几个,每次改动端点对出现次数的影响至多+1/-1,可以在 \(O(1)\) 的时间内完成更新,这个复杂度 \(O(n\sqrt n)\) 足以通过此题。这个做法不依赖于 “绝对” 众数,只要是众数就可以了。
  • 随机化: 随机 \([l,r]\) 内的一个数字,如果存在绝对众数,则找到的概率不小于 \(1/2\),随机 \(T\) 次,如果存在,则找到的概率至少是 \(p_T=1-(\frac{1}{2})^T\) ,对于 \(q\) 次询问,完全回答正确的概率大约是 \((1-(1/2)^T)^q\approx 1-q\times (1/2)^T\) ,取一个\(T=40\) 左右,就能让正确率达到\(1-10^{-7}\) 左右。
  • 线段树: 还是依赖于其绝对众数的性质,\([l,r]\) 内如果有绝对众数,第 \(\lceil\frac{r-l+1}{2}\rceil =1+\lfloor\frac{r-l}{2}\rfloor\) 大的数一定就是绝对众数。静态区间第 \(k\) 大问题,直接用可持久化线段树完成。
复杂度 适用 修改 实现
莫队 \(O(n\sqrt n)\) 众数 X 容易
随机化 \(O(n\log^2 n)\) 绝对众数 X 最容易
线段树 \(O(n\log n)\) 绝对众数 容易
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define dbg(x) cout<<#x"="<<x<<' '
using namespace std;
const int N=3e5+5;
int n,q,a[N],rt[N];
vector<vector<int>> pos;
struct Node{int v,ls,rs;};
template<int LOG=20>
class SegT{
    Node tr[N*LOG];
    int cnt_node;
public:
    void modify(int &x,int y,int l,int r,int p,int v){
        tr[x=++cnt_node]=tr[y];
        if(l==r){
            tr[x].v+=v;
            return;
        }
        int mid=l+(r-l>>1);
        if(mid>=p)modify(tr[x].ls,tr[y].ls,l,mid,p,v);
        else modify(tr[x].rs,tr[y].rs,mid+1,r,p,v);
        tr[x].v=tr[tr[x].ls].v+tr[tr[x].rs].v;
    }
    int query(int x,int y,int l,int r,int k){
        if(l==r)return l;
        int mid=l+(r-l>>1);
        int s=tr[tr[y].ls].v-tr[tr[x].ls].v;
        if(s>=k)return query(tr[x].ls,tr[y].ls,l,mid,k);
        return query(tr[x].rs,tr[y].rs,mid+1,r,k-s);
    }
};
SegT tr;
int main(){
    fastio;
    cin>>n>>q;
    pos=vector<vector<int>>(n+1);
    rep(i,1,n){
        cin>>a[i];
        pos[a[i]].push_back(i);
        tr.modify(rt[i],rt[i-1],1,n,a[i],1);
    }
    while(q--){
        int l,r,count,v;
        cin>>l>>r;
        v=tr.query(rt[l-1],rt[r],1,n,1+(r-l)/2);
        auto L=lower_bound(pos[v].begin(),pos[v].end(),l);
        auto R=prev(upper_bound(pos[v].begin(),pos[v].end(),r));
        if(L==pos[v].end())count=0;
        else count=(R-L)+1;
        if(2*count>=r-l+1)cout<<1+max(0,2*count-(r-l+1)-1)<<endl;
        else cout<<1<<endl;
    }
    return 0;
}

标签:CF1514D,int,tr,绝对,pos,随机化,ls,众数
From: https://www.cnblogs.com/yoshinow2001/p/18081195

相关文章

  • 代码随想录 第21天 | ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ●
    leetcode:530.二叉搜索树的最小绝对差-力扣(LeetCode)思路:判断最小绝对差,肯定用中序遍历,双指针一前一后依次判断。classSolution{intresult=Integer.MAX_VALUE;TreeNodepre=null;publicintgetMinimumDifference(TreeNoderoot){if(root==......
  • 501. 二叉搜索树中的众数c
    /***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*//***Note:Thereturnedarraymustbemalloced,assumecallercallsfree().*/intmax,sum,pre;void......
  • 代码随想录算法训练营day21 | leetcode 530. 二叉搜索树的最小绝对差、501. 二叉搜索
    目录题目链接:530.二叉搜索树的最小绝对差-简单题目链接:501.二叉搜索树中的众数-简单题目链接:236.二叉树的最近公共祖先-中等题目链接:530.二叉搜索树的最小绝对差-简单题目描述:给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,......
  • 随机化算法
    1随机化算法简介随机化算法,是一种十分玄学的做法。百度百科对其的定义是:随机化算法(randomizedalgorithm),是这样一种算法,在算法中使用了随机函数,且随机函数的返回值直接或者间接的影响了算法的执行流程或执行结果。就是将算法的某一步或某几步置于运气的控制之下,即该算法在运......
  • (20/60)二叉搜索树的最小绝对差、二叉搜索树中的众数、二叉树的最近公共祖先
    过外婆八十寿宴,补卡二叉搜索树的最小绝对差leetcode:530.二叉搜索树的最小绝对差双指针中序遍历法思路搜索树的最小绝对差一定出现在中序遍历的相邻两个元素之间。设置前后两个指针,每次对比“历史最小”与当前node->val-pre->val的值哪个更小,进行相应更新。复杂度分析......
  • 代码随想录算法训练营第二十天 | 236. 二叉树的最近公共祖先 , 501.二叉搜索树中的众
      530.二叉搜索树的最小绝对差 已解答简单 相关标签相关企业 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。差值是一个正数,其数值等于两值之差的绝对值。 示例1:输入:root=[4,2,6,1,3]输出:1示......
  • 随机化小结
    交互中的随机暂时还没怎么做,等以后来总结。我个人是比较认同OI-wiki对随机化技术的分类的,但是对于具体技术,这里不遵循OI-wiki的分类。1随机限制命中元素经典应用有:3-SAT(通过随机添加限制,然后弱化到2-SAT解决2借助期望/概率经典应用有:1、随机游走的最大距离期望是根号......
  • P8330 [ZJOI2022] 众数 题解
    Description给定一个长度为\(n\)的序列\(a_1,a_2,\dots,a_n\),问选一段区间,它的价值是里面的众数个数\(+\)外面的众数个数,求最大价值,以及所有满足这个最大价值的区间的外面的众数颜色。\(\sumn\leq5\times10^5,n\leq2\times10^5\)。Solution考虑根号分治。定义一个......
  • Ybt 金牌导航 6.3.A. 区间众数 / P4168 [Violet] 蒲公英(分块)
    题意简述多次查询区间\([l,r]\)的众数,若有多个取数值最小的。强制在线。\(n\le4\times10^4,m\le5\times10^4\)。分析考虑分块。首先预处理出块区间内的众数\(maj_{l,r}\)和每种数在某个块的前缀的出现次数\(cnt_{i,a_i}\),时空复杂度都是\(O(n\sqrtn)\)的。对于询......
  • SV 随机化(Randomization)
    CoverageDriverVerification可约束的随机化验证,用于测试的值可以再一定范围内进行随机,具体的范围可以进行约束,比如可以跑100次,然后查看覆盖率,可以通过覆盖率进行度量验证的进度内容随机化的变量往往需要添加一定的约束,通过添加约束让值在一定的范围内进行随机随......