CF1801 C. Music Festival [自定义偏序+dp+权值线段树]

传送门:CF

[前题提要]:自定义偏序来优化dp的递推,感觉这个trick很好,故记录一下


考虑对于同一张专辑,显然有贡献的序列是一个递增序列,所以我们可以直接对此进行删减.

接下来我们就获得了一些专辑,并且每张专辑的价值都是递增的.我们现在需要解决的问题是如何排列我们的专辑使得最后的贡献最大.

其实此时是不难想到 d p dp dp的,但是该如何 d p dp dp呢.

不难发现当我们枚举到第 i i i个物品的时候,我们想将其加入到我们之前的序列中,我们需要知道前缀的最大值,这样我们才能知道此时的 i i i增加的贡献是多少,所以我们考虑用一个 d p [ i ] [ j ] dp[i][j] dp[i][j]来记录加入了前 i i i个专辑,前缀最大值为 j j j时的最大贡献,但是此时我们又会发现存在这样一个问题,我们此时将 i i i插入到 j j j的后面,此时我们 i i i的贡献不难算出了,但是此时的 i i i会影响到前缀最大值,也就是会导致后序的贡献改变了.

也就是对于任意一个专辑,我们将其放在一个位置,它的贡献既会影响到前驱又会影响到后继.此时就很难进行维护了.此时思维似乎陷入了死胡同.

此时想一下是什么导致我们无法继续进行下去,是因为当前插入的那个物品影响到了后序的贡献,那么有没有一种做法,我们不会影响到后面呢.诶,你会发现只要当前插入的那个物品的最大值是之前i个最大的,那么此时无论我们的物品插入到哪里,后续的贡献都是0,也就是说,此时后续的贡献就是固定为0,也就不难维护了.顺着这个思路,我们会想到按最大值进行排序,这样就可以保证每次插入的物品都是前缀最大值了.(此处不得不吐槽一下,几乎所有的题解对此处的排序的解释都是贪心性排序,反正博主觉得根本不是这么一回事,此处的排序纯纯的只是为了我们的dp的递推方便而已,至于为什么它们这么一致,那就智者见智了)

此时插入一条简单的证明:我们对加入物品的顺序进行排序,并不会影响我们最终的最优性策略.感性的想一下就是我们运用的方法是动态规划,也就是我们将所有的可能性都是保留的,在最后一刻才将所有的策略取一个最优解.理性的想一下:考虑对一串序列 a 1 , a 2 , a 3 , . . , a n a_1,a_2,a_3,..,a_n a1,a2,a3,..,an,我们此时分别需要插入 a n + 1 , a n + 2 a_{n+1},a_{n+2} an+1,an+2这两个数字,我们考虑先加入 a n + 1 a_{n+1} an+1再加入 a n + 2 a_{n+2} an+2,假设上述两个数字分别插在 p o s 1 , p o s 2 pos1,pos2 pos1,pos2的位置,显然这两个位置是互不影响的(也就是说第一个位置并不会影响第二个位置的存放),所以当我们先加入 a n + 2 a_{n+2} an+2的时候,我们此时仍然可以将其放在 p o s 2 pos2 pos2的位置.并且对于动态规划来说,上述四种状态都会被存下来,所以正确性是对的.

所以考虑先对其进行排序,然后考虑用一个 d p [ i ] [ j ] dp[i][j] dp[i][j]来记录加入了前 i i i个专辑,前缀最大值为 j j j时的最大贡献即可.为了快速的查找最大值,这是个 R M Q RMQ RMQ问题,我们可以使用多种数据结构来进行动态维护.博主使用的是权值线段树.

需要注意的一点细节是并不能对于每一个测试样例都建一棵树,这样的复杂度会假.(别问为什么我知道,因为我实现的时候就是这么实现的,然后T了.此时让我想起了之前每次实现权值线段树的时候要么是离线,要么没有多组数据,所以一直没有遇到过这种情况).当然如果你的dp方程稍微改一下,改成前i个专辑,前缀最大值的下标是j专辑的最大贡献,这样就可以每次都建一颗树了.


下面是具体的代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {ll x=0,w=1;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';return x*w;
}
inline void print(__int128 x){if(x<0) {putchar('-');x=-x;}if(x>9) print(x/10);putchar(x%10+'0');
}
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Segment_tree{int l,r,mx;
}tree[maxn<<2];
void pushup(int rt) {tree[rt].mx=max(tree[ls].mx,tree[rs].mx);
}
void build(int l,int r,int rt) {tree[rt].l=l;tree[rt].r=r;tree[rt].mx=-int_INF;if(l==r) {return ;}int mid=(l+r)>>1;build(lson);build(rson);pushup(rt);
}
void update(int pos,int val,int rt) {if(tree[rt].l==pos&&tree[rt].r==pos) {tree[rt].mx=max(tree[rt].mx,val);return ;}int mid=(tree[rt].l+tree[rt].r)>>1;if(pos<=mid) update(pos,val,ls);else update(pos,val,rs);pushup(rt);
}
void reset(int pos,int val,int rt) {if(tree[rt].l==pos&&tree[rt].r==pos) {tree[rt].mx=val;return ;}int mid=(tree[rt].l+tree[rt].r)>>1;if(pos<=mid) reset(pos,val,ls);else reset(pos,val,rs);pushup(rt);
}
int query(int l,int r,int rt) {if(tree[rt].l==l&&tree[rt].r==r) {return tree[rt].mx;}int mid=(tree[rt].l+tree[rt].r)>>1;if(r<=mid) return query(l,r,ls);else if(l>mid) return query(l,r,rs);else return max(query(l,mid,ls),query(mid+1,r,rs));
}
int k[maxn];vector<int>a[maxn];int dp[maxn];
bool cmp(vector<int>&A,vector<int>&B) {return A.back()<B.back();
}
int main() {int T=read();build(1,2e5,1);while(T--) {int n=read();for(int i=1;i<=n;i++) {k[i]=read();for(int j=1;j<=k[i];j++) {int num=read();if((int)a[i].size()!=0&&num<=a[i].back()) {continue;}else {a[i].push_back(num);}}k[i]=a[i].size();}
//		build(1,2e5,1);这里复杂度假了,Tvlogvsort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++) {for(int j=0;j<a[i].size();j++) {if(a[i][j]==1) {dp[a[i].back()]=max(dp[a[i].back()],(int)a[i].size()-j);}else {int num=query(1,a[i][j]-1,1);if(num==-int_INF) num=0;dp[a[i].back()]=max(dp[a[i].back()],num+(int)a[i].size()-j);}}update(a[i].back(),dp[a[i].back()],1);}int ans=-int_INF;for(int i=1;i<=n;i++) {ans=max(ans,dp[a[i].back()]);}printf("%d\n",ans);//clearfor(int i=1;i<=n;i++) {reset(a[i].back(),-int_INF,1);dp[a[i].back()]=0;a[i].clear();}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/773914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能文档处理技术综述

一、 智能文档处理介绍 智能文档处理&#xff08;Intelligent Document Processing, IDP&#xff09;是利用人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&#xff09;、计算机视觉&#xff08;CV&#xff09;、自然语言处理&#xff08;NLP&#xff09;等技术…

机器学习笔记(2)—单变量线性回归

单变量线性回归 单变量线性回归(Linear Regression with One Variable)1.1 模型表示1.2 代价函数1.3 代价函数的直观理解1.4 梯度下降1.5 梯度下降的直观理解1.6 梯度下降的线性回归 单变量线性回归(Linear Regression with One Variable) ps:...今天很倒霉 一名小女孩悄悄地碎…

Redhat7安装yum源,解决报错No more mirrors to try...

运行yum出现报错 或者 bash: yum: command not found...的提示&#xff0c;按照此篇文章重新安装yum并配置源即可。 前提 Linux系统为redhat7&#xff0c;且可以通外网 步骤一&#xff1a;卸载原有yum 使用rpm -qa | grep yum 查看 rpm -qa|grep yum|xargs rpm -e --node…

极端道路天气数据集 雨天 雾天 道路晴朗

极端道路天气数据集 是一系列专为自动驾驶、智能交通系统研发以及计算机视觉算法测试而设计的真实世界或模拟的道路环境图像和视频集合。这些数据集包含了在各类极端天气条件下捕捉到的道路场景&#xff0c;例如大雾、暴雨、暴雪、冰雹、雾霾、道路结冰等&#xff0c;这些都是…

文件缓存系统(90%用例)C卷(JavaPythonC++Node.jsC语言)

请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)。 文件缓存系统有两种操作:存储文件(put)和读取文件(get)操作命令为put fileName fileSize或者get fileName 存储文件是把文件放入文件缓存系统中;读取文件是从文件缓存系统中访问已存在的文件,如果文…

【数据分享】1929-2023年全球站点的逐日平均海平面压力(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2023年全球气象站…

【C++中的STL(未完成)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

Vue.js高效前端开发(增删查)

效果图 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><div id"app"><span>ID</span><input type"text" name"…

震惊!C语言是这样操作文件的!

文章目录 文件指针概述文件指针打开模式文件常用操作函数fprintf&#xff08;&#xff09;函数fscanf&#xff08;&#xff09;函数fgets&#xff08;&#xff09;函数fputc&#xff08;&#xff09;函数fgetc&#xff08;&#xff09;函数feek&#xff08;&#xff09;函数fre…

AI程序员崛起:人类的饭碗真的会被抢走吗?

近期&#xff0c;全球首位AI程序员Devin的惊艳亮相&#xff0c;在科技界引起了不小的轰动。AI程序员的出现&#xff0c;让人们不禁开始思考一个问题&#xff1a;这些智能编程助手会不会抢走程序员的饭碗&#xff1f;对此&#xff0c;我认为我们需要保持冷静&#xff0c;理性看待…

检验pandas数据中的空值 (DataFrame, 某列,某具体空格)

构建测试数据 创建一个包含空值的DataFrame data {A: [1, 2, np.nan, 4],B: [5, np.nan, 7, 8],C: [np.nan, 10, 11, 12] } df pd.DataFrame(data) 检测 DataFrame 中是否存在空值 null_values pd.isnull(df)# 打印结果 print(null_values)A B C 0 1.0 5.0 Na…

如何在Java中创建Excel表单控件

前言 在数据填报时&#xff0c;创建Excel表单控件是一项常见的任务&#xff0c;它可以极大地简化数据收集和处理的过程。传统的做法需要在Excel中开启开发工具&#xff0c;并且自己手动添加&#xff0c;如下图&#xff0c;就是一个常见的表单控件。 而在Java中&#xff0c;可…

Linux 设备树: of_property_match_string 的用法与工作原理

前言 当前新版本的 Linux 内核 设备驱动框架&#xff0c;与设备树&#xff08;Device Tree&#xff09;结合密切&#xff0c;整体 设备树的设备驱动框架&#xff0c;比较的庞大&#xff0c;但又非常的经典。 一个个的 设备树解析函数&#xff0c;都是前人【智慧】的结晶&#…

dijkstra算法及模板题

⭐️dijkstra 介绍&#xff08;想看的可以看&#xff09; Dijkstra算法&#xff08; /ˈdaɪkstrəz/ DYKE-str z&#xff09;是一种用于找到加权图中的节点之间的最短路径的算法&#xff0c;该加权图可以表示例如道路网络。它是由计算机科学家Edsger W. Dijkstra于1956年出版…

吴恩达ReinforcementLearning Docker镜像构筑

Reinforcement Learning课程Docker镜像制作 前提从Dockerfile构建可用image最后 前提 参照吴恩达机器学习环境本地化构建wsldockertensorflowcuda的1~3构建了Docker可运行的环境 从Dockerfile构建可用image 下载附件并命名为的Dockerfile 在Dockerfile所在的文件夹下运行 do…

docker的dockerfile

FROM Dockerfile中的第一个指令&#xff0c;也是一个必须的指令。它用于指定构建新镜像时所基于的基础镜像。 FROM <image>:<tag> FROM nginx:1.25.1-alpineRUN 指令在Dockerfile中可以出现多次&#xff0c;并且每个RUN指令都会创建一个新的镜像层。为了减少镜像…

富格林:梳理正规本领远离虚假套路

富格林悉知&#xff0c;黄金投资者在从事黄金交易之前&#xff0c;必须先了解黄金交易的风险。因为投资虽然能给你带来一定的收益&#xff0c;但往往也有亏损的风险。在进场后投资者可通过正规经验指导有效避免因为虚假诱导带来的异常亏损&#xff0c;增加安全做单盈利机会。以…

DC电源模块与其他电源模块有着明显的区别与优势

DC电源模块与其他电源模块有着明显的区别与优势 BOSHIDA DC电源模块&#xff08;Direct Current Power Supply Module&#xff09;是一种将交流电转换为直流电的设备&#xff0c;常用于电子设备和工业控制系统中。与其他电源模块相比&#xff0c;DC电源模块有一些明显的区别和…

R语言ggplot2 | 热图+随机森林重要性!升级版~

&#x1f4cb;文章目录 原图复现定义ggrf_ggcor_plot()函数加载数据集一键出图函数优点 今天推出一个升级版&#xff1a; ggrf_ggcor_plot的函数。只需要输入 响应变量的矩阵和 解释变量的矩阵&#xff0c;就能轻松一键生成随机森林重要性相关性热图。 原图 所需复现的随机森…

推荐5款测试数据生成工具!

一个成功、有效的测试策略由下面几个基本部分组成&#xff1a;完整的测试覆盖率、最小化的环境影响和健壮的测试数据。 其中测试数据尤其重要&#xff0c;其质量直接关系到测试的有效性。可以把测试数据看作是保持测试引擎运行的燃料——高质量的测试数据有助于确保测试执行的…