hdu 5324 树套树、cdq分治

[BZOJ3295] [Cqoi2011]动态逆序对 (树套树)or(CDQ分治) 题意:N个数的排列,M次操作,每次求当前的逆序对数量并删掉一个数。 先说一下cdq分治做法。(5960kb,1.4s) 网上很多题解,我都看不懂(其实很多人的程序几乎是一样的,就改了一下变量名),然后就自己硬着头皮想了这道题,基本是独立做出来的,做出来之后竟然1A,简直愉快。不过我太辣鸡了想了半天才发现这本质上是一个三维偏序,分别是时间,下标,数值,记为(t,x,y)。 我们可以把删 阅读详情

一、线段树/树状数组套平衡树

题目大意是给你n个(L[i], R[i])的点,找出最长的子序列,满足L[i]递减,R[i]递增。为了看起来顺眼点,我们可以把其中一维取相反数,使得两个都找递减,或者都找递增的。

我们把L[i]取相反数,找两个都递增的。假设不考虑R[i],只考虑L[i],那么就相当于LIS问题了。


dp[i]记录以L[i]为结尾的最大长度,dp[i]=max{dp[j]}+1,其中L[j]<=L[i]。问题就在于,找到满足<=L[i]的最大值。这时候我们可以将L[i],离散化用线段树维护区间最大值。对于,dp[i]我们查询区间[1,L[i]]的最大值更新dp[i],然后将位置L[i]的最大值更新为dp[i],后面循环这一操作就能得到答案。

而这个问题还多了一维,还要处理R[i]的递增关系,那么线段树里维护不仅仅是最大值dp[i],而是需要维护(R[i],dp[i])这样的值对。对于更新dp[i]的时候,我们首先还是要先找[1,L[i]]所对应的区间节点,然后在这些节点里找到满足R[j]<=R[i]最大的dp[j]值。按照处理L的方法,我们应该用一棵平衡树来维护(R[i], dp[i])这样的键值对,来达到快速查找R[j]<=R[i]的目的。所以线段树区间里维护的不是最大值了,而是一棵平衡树,而平衡树维护的是(R[i],dp[i])键值对。

所以查找最大值就是,先找到线段树里[1,L[i]]的所有覆盖区间,然后对于每一个区间在平衡树里查找<=R[i]的最大值。复杂度是logn*logn。


总体时间复杂度O(n*logn*logn)。更新的时候,单点更新,每个点要经过logn个区间,也就是插入logn棵平衡树,所以空间复杂度是O(nlogn),平衡树开一个20*n的内存池存储。


这题要求字典序最小,可以用逆序处理。从左到右处理dp[i]得到的是以第i个为结尾的最长长度,我们想要的是开头尽可能小,那么从右到左扫就是得到以i为开头的最大长度。

平衡树之前没写过,照着模板学着敲SBT的,代码写的很冗长就不贴了。

还有这里用树状数组求最大值会比线段树快很多,1300ms和2200ms。。。




二、cdq分治

这个是看了博客 http://blog.youkuaiyun.com/u013007900/article/details/47111319     学的。模仿着写了一遍。复杂度是T(n)=T(n/2)+O(nlogn),所以是O(nlogn*logn)。其中可以优化的地方就是,每一层分治的时候所需要的排序,可以通过预先归并排序,并记录归并中每一层的排序结果来优化。用归并优化后时间从1100ms->600ms。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=50010;
typedef pair<int, int> Pr;

int n,m;
int a[maxn],b[maxn];
int dp[maxn], pre[maxn];


struct P
{
	int x,y;
	int id;
    P(){}
    P(int xx, int yy, int dd):x(xx),y(yy), id(dd){}
	bool operator <(const P & a) const
	{
		return x!=a.x?x>a.x:id<a.id;
	}

};

P arr[maxn];
P sorted[20][maxn];//记录每一层的归并排序结果
P c[maxn];
Pr bit[maxn];


//归并排序
void merge_sort(int l, int r, int dep)
{
    if(l==r){
        sorted[dep][l]=arr[l];
        return;
    }
    int m=(l+r)>>1;
    merge_sort(l, m, dep+1);
    merge_sort(m+1, r, dep+1);
    merge(sorted[dep+1]+l, sorted[dep+1]+m+1, sorted[dep+1]+m+1, sorted[dep+1]+r+1, sorted[dep]+l);
}

void init(int n)
{
	for(int i=1; i<=n; i++)
		bit[i]=Pr(0,0);
}

void update(int x,  Pr v)
{
	while(x<=n){
		bit[x]=max(bit[x], v);
		x+=(x&-x);
	}
}

void clr(int x) //用于清空树状数组的update操作,这样就不用每次都把整个数组初始化一遍。
{
    while(x<=n){
		bit[x]=Pr(0,0);
		x+=(x&-x);
	}
}

Pr query(int x)
{
	Pr ret(0,0);
	while(x){
		ret=max(bit[x], ret);
		x-=(x&-x);
	}
	return ret;
}

//cdq分治
void solve(int l, int r, int dep)
{
    if(l==r){
        dp[arr[l].id]=max(dp[arr[l].id],1);
        return;
    }

    int m=(l+r)>>1;
    solve(m+1, r,dep+1);

    for(int i=l; i<=m; i++)
        c[i]=arr[i];

    for(int i=l; i<m+1; i++)
        arr[i]=sorted[dep+1][i]; //排序,直接从归并结果里面提取

    int ptr=r;
    for(int i=m; i>=l; i--){
        while(ptr>m && arr[ptr].x<=arr[i].x){
            update(arr[ptr].y,  Pr(dp[arr[ptr].id], -arr[ptr].id));
            ptr--;

        }

        int cur=arr[i].id;
        Pr maxi=query(arr[i].y);
        dp[cur]=max(dp[pre[cur]]+1, dp[cur]);
        Pr tmp(dp[pre[cur]], -pre[cur]);
        if(maxi>tmp){
            dp[cur]=maxi.first+1;
            pre[cur]=-maxi.second;
        }
    }
    for(int i=r; i>ptr; i--) //清空树状数组
        clr(arr[i].y);

    for(int i=l; i<=m; i++) arr[i]=c[i];
    solve(l, m, dep+1);
    
    for(int i=l; i<=r; i++) //合并排序
        arr[i]=sorted[dep][i];
}

int main()
{
	while(cin>>n){
		for(int i=1; i<=n; i++){
			scanf("%d", a+i);
		}
		for(int i=1; i<=n; i++){
			scanf("%d", b+i);
			arr[i]=P(a[i], -b[i], i); //第二维取相反数,求两个都递减的最大长度。
			b[i]=-b[i];
		}
		sort(b+1, b+1+n);
		for(int i=1; i<=n; i++){
            arr[i].y=lower_bound(b+1,b+1+n,arr[i].y)-b; //离散化用于树状数组求最大值
		}


        memset(dp, 0, sizeof(dp));
        memset(pre, 0, sizeof(pre));
        init(n);
        merge_sort(1, n, 0);
		solve(1, n, 0);

		int ind=0, ans=0;;
		for(int i=1; i<=n; i++){
			if(dp[i]>ans){
				ans=dp[i];
				ind=i;
			}
		}

		printf("%d\n", ans);
		while(pre[ind]!=0){
			printf("%d ", ind);
			ind=pre[ind];
		}
		printf("%d\n",  ind);
	}
    return 0;
}





基于Isaac Gym与PPO算法的机械臂抓取任务仿真与强化学习实战(附完整代码与训练策略) 本文详细介绍了基于Isaac Gym与PPO算法的机械臂抓取任务仿真与强化学习实战。通过环境搭建、PPO算法实现、奖励函数设计等核心环节的优化,结合完整代码与训练策略,显著提升机械臂抓取效率与成功率。特别适合开发者快速掌握强化学习在机器人控制领域的应用。 阅读详情

相关推荐

FPGA:UART串口接收(高干扰情况)

在上一篇文章中介绍过UART串口接收模块,其中一个需要优化的方向就是在高干扰情况下,如何实现可靠的UART串口接收任务。

weixin_50164178的博客 1672

CDQ-分治和树套树 的结合小结

为什么要将这两个东西放在一起讨论呢?最近出于熟悉至彻底掌握cdq的目的 我去看了很多例题,希望能在其中发现cdq解题的特点和套路,进而真正把握精髓。可能是因为资源选的不好,这些题目简化后大都大同小异,所以我学习时担心有一些稀奇的cdq应用方法没有见识到。可能会造成知识的片面。 就算是这样,我想目前还是积累了一些浅薄的思想,大概有以下 我觉得cdq是一个简单的算法,但是它的思想很有价值。我时常

WDCnew的博客 686

工程经验分享:PCIE(1)

本文介绍AXI Bridge For Pcie Express Gen3 Subsystem 的使用方法。这个IP兼具简单与实用性,将PCIE协议层实现于内部,仅留出AXI接口供开发者使用。开发者不需要处理复杂的PCIE协议数据,只需要对AXI总线有所了解即可,十分符合Xilinx一贯的开发风格。本文无关PCIE协议本身,仅分享实用性的工程经验,以PCIE IP为核心,一步一步搭建一个简单的子系统,以此说明用法。文中所有内容均已通过项目检验。

weixin_42415266的博客 3842

树套树练习

树套树讲题T1:二逼平衡树(树套树)题解代码[国家集训队]排队题解代码动态逆序对题解代码k大数查询题解(by zxy)代码 T1:二逼平衡树(树套树) 传送门 题解 所谓树套树呢?就是把两棵不同的树套在一起,以达到意想不到的效果。 对于这道题,可以线段树套平衡树,也就是每个点维护一个平衡树,下面我来分别讲解一下每种操作。 查询k在区间内的排名 把区间分解成线段树上的点,查询kkk在每个点上的排名-...

qq_42371755的博客 691

天融信防火墙NGFW4000(TG-4628)安装配置笔记

配置一台全新的天融信防火墙NGFW4000,配置完后,内网用户10.10.1.0/24和10.10.2.0/24可以通过防火墙上网,外网用户可以通过访问防火墙的外网接口地址来访问内网的WEB服务器10.10.1.200,并且内网用户也可以通过WEB服务器的外网地址进行访问。 网络说明: 防火墙外网接口地址:218.90.123.121/30 防火墙内网接口地址:19...

weixin_33671935的博客 4455

AT91SAM9260搭建LINUX操作系统

一、 编写目的 2 二、 系统搭建 2 1. 下载相关软件包 2 2. Bootstrap编译 3 3. U-BOOT编译 5 4. LINUX编译 7 5. 通过U-BOOT的TFTP命令从TFTP服务器下载系统镜像 9 6. 文件系统制作 10 7. 挂载NFS作为根文件系统 10 三、 总结 14 一、编写目的 本文档用于记录AT91SAM9260 LINUX学

lshiceman的专栏 7412

树套树

之前写的线段树常用方法 概念 注:参考博客里最后一句话(多行修改很难实现,因为x树的Lazy-tag是区间,无法合并)仅针对x树,y树依然可以区间修改(具体原因下文会结合题目说明) HDU4819 原题地址 题目大意:给一个N*N的矩阵,每次给一个命令取反一个子矩阵,或者查询其中某一点的01状态。 代码: 代码来自于参考博客 #include<cstdio> #include<cstring> #include<algorithm> using namespace std

weixin_43918350的博客 231

磁编码器选型避坑指南:为什么MT6816比霍尔传感器更适合你的伺服系统?

本文深入对比了MT6816磁编码器与传统霍尔传感器在伺服系统中的应用。MT6816基于AMR技术,对磁场方向敏感而非强度,具备高精度、强抗干扰、高安装容差和极低延时等优势,尤其适合高转速、恶劣环境下的工业场景,能有效提升系统可靠性与长期稳定性。

rainy的博客 1103

HDU 5324 Boring Class 树状数组套平衡树

Boring Class Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Mr. Zstu and Mr. Hdu are taking a boring class , Mr. Zstu comes up wit

上决╇ф的ACM 802

改进yolov8|BackBone改进:PWConv、FasterNeXt替换yolov8主干网络

各位哥哥姐姐弟弟妹妹大家好,我是干饭王刘姐,主业干饭,主业2.0计算机研究生在读。和我一起来改进yolov8变身计算机大牛吧!本文中的论文笔记都是刘姐亲自整理,原创整理哦~

weixin_44379985的博客 748

手把手教你学Simulink--基于光伏(PV)系统的建模与仿真场景:-不同天气条件下光伏系统的输出性能分析

本文介绍了使用Simulink和Simscape Electrical工具箱进行光伏系统建模与仿真的完整流程。内容涵盖准备工作、模型构建、仿真分析三大步骤,重点演示了如何模拟不同天气条件(光照强度、温度变化)对光伏输出性能的影响。通过添加PVArray模块、配置参数、设置环境变化条件、连接测量仪器等操作,实现了光伏系统在动态天气条件下的输出特性分析。文章还提供了仿真参数设置建议和结果分析方法,帮助用户理解环境因素与光伏性能的关联性,为光伏系统设计和优化提供参考。

MHD0815的博客 189

Python交互式开发环境:IPython与Jupyter Notebook详解

Python作为解释型语言,其交互式开发环境对提高编程效率至关重要。IPython作为标准Python解释器的增强版本,通过Tab补全、对象自省和魔术命令等功能,极大提升了代码编写和调试体验。Jupyter Notebook则进一步将交互式计算与富文本结合,成为数据分析和科学计算的首选工具。这两种工具都支持Python核心语法,包括列表、字典等数据结构以及控制流程,特别适合快速原型开发和数据探索。掌握IPython和Jupyter Notebook的使用技巧,能够帮助开发者更高效地进行Python编程和数据

408

MCU-内部flash模拟成EepRom(重新梳理)

通过fee写数据Data的过程中,数据会mapping一个虚拟地址,这个虚拟地址就是你的身份,在向flash写数据的过程中会写入很多相同虚拟地址的不同数据,在读取或切页的过程中,遍历数据只会认为最下面第一个的虚拟地址所持有的数据是有效数据,其他的都是老数据,可以丢弃。模拟成eeprom的两个eep_page写数据逻辑就是,先在eep_page0写数据,eep_page0写满后,将eep_page0的有效数据copy到eep_page1,之后擦eep_page0;

xiandang8023的博客 711

HDU 5324 Boring Class 树套树 或 CDQ分治

HDU 5324 Boring Class 树套树 或 CDQ分治题目链接:HDU 5324 题意: 给定两个序列,求一个最长的公共子序列使得第一个子序列递减,第二个递增。 思路: 将L数组的下标排序并从小到大插入,维护一个满足R的最大DP值的位置。二维。如果内存够大可以,线段树套线段树,可以用线段树套SPLAY。 代码:#include <cstdio> #include <cstrin

alpc_paul的专栏 1249

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

HDU--5324(CDQ分治,DP)

2015-08-1622:20:21 【传送门】 Pre:Jay巨出的题~最近在补CDQ,这题当然要做辣!在已经做过CDQ+DP题的前提下,这题就不难做了~ 题意:给出两列数L1~Ln,R1~Rn,求出字典序最小的最长的子序列下标(可离散),满足L非严格递减,R非严格递增。(n <= 50000) 思路:典型的DP,可以用树套树优化到N(logN)^2,但是显然用CDQ更...

dingdi3021的博客 237

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

hdu 5324 Boring Class

题目描述:给出两个序列L[i], R[i],求出最长的子序列v[i]满足: v(1) ≥ 1, v(m) ≤ n,v(i) < v(i + 1). (for i from 1 to m - 1) L(v(i)) ≥ L(v(i + 1)), R(v(i)) ≤ R(v(i + 1))(for i from 1 to m - 1) n~1e5;题解:转化成求同时两个的最长单调不降子序列. 对于

ruclion的专栏 434

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

hdu_5324_Boring Class(cdq分治+树状数组)

题目链接:hdu_5324_Boring Class 题意: 给出n个二维点对,求LIS长度和编号字典序最小的LIS(x非增,y非减) 题解: dp[i]=max(dp[j]) (i>j,l[i]>=l[j],r[i]<=r[i]) 一看就是三维偏序问题。 如果树套树写的好,空间开的大的话,一样可以过,不过这里还是用cdq分治套树状数组好写一点。 用lowbit来...

weixin_30456039的博客 156

hdu 5412 CRB and Queries(线段树套笛卡尔树 - 动态区间第k大)

题目链接:hdu 5412 CRB and Queries 首先对所有出现过的值排序,建立线段树,每个线段树的节点是一棵笛卡尔树,笛卡尔树记录区间下标值。 #include #include #include #include using namespace std; #define lson(x) (x<<1) #define rson(x) ((x<<1)|1)

不慌不忙、不急不躁 1380

HDU 5324 分治

很好的题,看完题意原本以为十几分钟就能AC,结果WA了一整天,修改重交十几次终于AC,通过此题,加深了对分治算法的理解和码力。 题意很简单,一个三维偏序的变形。 但差别在于x坐标是已经排列好且去重的数据给出顺序。 要你求满足Y非严递减和Z非严递增的最长三维偏序列。易掉的坑:(其实是我掉的坑qwq) (1).直接仿造HDU 5618的做法是不对的,因为此题要求最长序列任意两两之间均满足约束关系。

新熊君的博客 677

HDU5324 Boring Class(树状数组 + CDQ分治)

题意:给两个序列L, R, 序列元素个数都是n, 现在要找一个序列v1, v2...vm, 使得满足条件: 1.vi 2.L[vi] >= L[vi+1] && R[vi] 思路: 这个dp的状态转移方程很好找,如果将R元素乘以一个负数,则就是求L[vi] >= L[vi+1] && R[vi] >= R[vi+1]了,  这个二维点的偏序关系论文专门讲过树状数组套树状数组的,

hnust_Derker的博客 486

hdu 5618 树套树和cdq分治

Jam’s problem again Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1746 Accepted Submission(s): 623 Problem Description Jam like to sol...

zstu_zy的博客 287

hdu 5324 Boring Class(树状数组+笛卡尔树 | 树状数组+cdq分治)

题目链接:hdu 5324 Boring Class 做法一:树状数组套笛卡尔树。 保证字典序最小,从N->1方向遍历。树状数组维护第二维,每个节点对应一棵笛卡尔树,笛卡尔树的key值对应第三维,val值为随机值,控制树高。然后笛卡尔树的每个节点维护len,idx,mlen,midx将每次查询复杂度控制在log(n) * log(n) #include #include #inc

不慌不忙、不急不躁 1179

HDU 4742 (CDQ分治 树状数组)

题目链接:点击这里题意:三维LIS。给出空间的n个点,求出最长的序列和方案数,要求序列的后一个点三个坐标都不小于前一个点。先排序掉一维,然后剩下两维分治, 用一个带长度和方案数的结构体树状数组维护。“`C++include include include include include include using namespace std;define maxn 100005define mod

morejarphone~ 1107

hdu 4819 Mosaic(树套树型二维线段树)

Mosaic Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 892    Accepted Submission(s): 388 Problem Description The God of sheep decid

llin-黎辰 916

HDU-5324 cdq分治

Boring Class Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1444    Accepted Submission(s): 460 Problem Description Mr. Zstu and M

AC_Machine的博客 893

hdu 2544 最短路(floyd算法)

题意:就不再说了,用floyd 算法时 复杂度蛮高的 但是 代码简单 超级简单 连接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 View Code #include <iostream>//floyd 算法 很简单的floyd using namespace std; #define INF 0xfffff...

172
上一篇: hdu 4630 线段树+离线处理
下一篇: poj 1741 树分治入门
HuanTongH
博客等级 码龄12年 7粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值