首页 > 其他分享 >整体二分学习笔记

整体二分学习笔记

时间:2023-06-16 12:57:12浏览次数:28  
标签:二分 int mid 笔记 1000001 学习 include check

概念

对于一个很多询问的题,假如对于一个询问可以二分处理,同时一次 check 可以只用 \(n\) 的时间处理所有询问的 check 结果,我们可以使用整体二分来做这个题。

思想

设函数 \(\operatorname{solve}(S, L, R)\) 为现在正在处理询问序列 \(S\) 里的询问,答案值域为 \([L, R]\)。

向下递归直到 \(L=R\),即求出了答案。

否则对于 \(mid\) 执行 check,比较并将 \(S\) 分成两部分向下递归 \([l,mid]\),\([mid+1,r]\)。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a[1000001],lsh[1000001],ans[1000001];
struct qw
{
	int op,l,r,k,i;
}q[1000001],lt[1000001],rt[1000001];
int snmn[1000001];
void add(int x,int w)
{
	while(x<=n)
	{
		snmn[x]+=w; 
		x+=(x&(-x));
	}
}
int sum(int x)
{
	int re=0;
	while(x)
	{
		re+=snmn[x];
		x-=(x&(-x));
	}
	return re;
}
void tp(int l,int r,int L,int R) //l-r询问 L-R答案
{
	int ll=0,rl=0;
	if(l>r) return;
	if(L==R)
	{
		for(int i=l;i<=r;i++)
		{
			if(q[i].op==1) continue;
			ans[q[i].i]=L; 
		}
		return;
	}
	int mid=L+R>>1;
	for(int i=l;i<=r;i++)
	{
		if(q[i].op==1)
		{
			if(q[i].r<=mid)
			{
				add(q[i].k,1);
				lt[++ll]=q[i];
			}
			else
			{
				rt[++rl]=q[i];
			}
		}
		else
		{
			int cnt=sum(q[i].r)-sum(q[i].l-1);
			if(q[i].k<=cnt)
	  		{
				lt[++ll]=q[i];
			}
			else
			{
				q[i].k-=cnt;
				rt[++rl]=q[i];
			}
		}
	}
	for(int i=l;i<=r;i++)
	{
		if(q[i].op==1&&q[i].r<=mid) add(q[i].k,-1);
	}
	for(int i=1;i<=ll;i++)
	{
		q[l+i-1]=lt[i];
	}
	for(int i=1;i<=rl;i++)
	{
		q[l+ll+i-1]=rt[i];
	}
	tp(l,l+ll-1,L,mid);
	tp(l+ll,r,mid+1,R);
}
signed main()
{
	scanf("%d%d",&n,&m);
	m+=n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		lsh[i]=a[i];
	}
	sort(lsh+1,lsh+n+1);
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(lsh+1,lsh+n+1,a[i])-lsh;
	}
	for(int i=1;i<=n;i++)
	{
		q[i].r=a[i];
		q[i].k=i;
		q[i].op=1;
	}
	for(int i=n+1;i<=m;i++)
	{
		q[i].op=2;
		scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
		q[i].i=i-n;
	}
	tp(1,m,1,n);
	for(int i=1;i<=m-n;i++)
	{
		printf("%d\n",lsh[ans[i]]);
	}
}

标签:二分,int,mid,笔记,1000001,学习,include,check
From: https://www.cnblogs.com/lizhous/p/17485276.html

相关文章

  • 【笔记】learning git branching
    git图是由子节点指向父节点(可能有多个父节点)gitcommitgitbranchgitmergegitrebase......
  • 系统架构设计师笔记第16期:数据库基本概念
    数据库技术的发展数据库技术在过去几十年中经历了显著的发展和演变。层次数据库和网状数据库:20世纪60年代和70年代初,层次数据库和网状数据库是主流的数据库模型。层次数据库使用树状结构组织数据,而网状数据库使用复杂的网络结构。这些数据库模型适用于特定的数据组织和查询需求,但缺......
  • Markdown语法学习记录
    ##小记markdown语法是写博客所需要的基本的语法,而且也比较容易掌握,以下是我个人学习的基础的语法。##标题一共有六级标题,先说一级标题一级标题的语法是#+空格+标题二级标题的语法是##+空格+标题 ......想创建多少级的标题就在前面加多少个#号##字体**粗体***斜体*......
  • 了解基于模型的元学习:Learning to Learn优化策略和Meta-Learner LSTM
    摘要:本文主要为大家讲解基于模型的元学习中的LearningtoLearn优化策略和Meta-LearnerLSTM。本文分享自华为云社区《深度学习应用篇-元学习[16]:基于模型的元学习-LearningtoLearn优化策略、Meta-LearnerLSTM》,作者:汀丶。1.LearningtoLearnLearningtoLearnbyGradien......
  • MyBatis-Plus学习
    一、MyBatis-Plus简介1、简介MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。2、特性无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑损耗小:启动即会自动注入基本CURD,性能基本无损耗,直接面向对......
  • 时间序列异常检测:统计和机器学习方法介绍
    理解时间序列数据在深入研究异常检测技术之前,先简单介绍时间序列数据的特征。时间序列数据通常具有以下属性:趋势:数据值随时间的长期增加或减少。季节性:以固定间隔重复的模式或循环。自相关:当前观测值与先前观测值之间的相关性。噪声:数据中的随机波动或不规则。让我们......
  • Python 初学笔记
    1.注释:与c和cpp不一样,python的注释不是//或者/**/,而是#.....  //单行注释多行注释"""......."""                         //多行注释type()     //查看数据的类型,在括号里面填入查看数据的信息数据类型转......
  • File I/O学习总结
    1.File文件的增删查(1)增publicvoidaddFile(Filefile){file.createNewFile();}(2)删publicvoiddeleteFile(Filefile){file.delete();}(3)查publicvoidfindFile(Filefile){file.getName();file.getAbsolutePath();}2.流的指向(1)读入【文件读入到......
  • 国产MCU-CW32F030开发学习--按键检测
    国产MCU-CW32F030开发学习--按键检测bsp_key按键驱动程序用于扫描独立按键,具有软件滤波机制,采用FIFO机制保存键值。可以检测如下事件:按键按下。按键弹起。长按键。长按时自动连发。我们将按键驱动分为两个部分来介绍,一部分是FIFO的实现,一部分是按键检测的实现......
  • 文本分类与情感分析:基于深度学习的大型语言模型应用
    目录1.引言2.技术原理及概念3.实现步骤与流程4.示例与应用5.优化与改进6.结论与展望7.附录:常见问题与解答文本分类和情感分析是人工智能领域中非常重要的技术,其应用广泛,包括自然语言处理、语音识别、计算机视觉等多个领域。本文将介绍基于深度学习的大型语言模型应用文本......