[Tricks-00002]CF2026F 操作建树维护带删deque信息的经典套路

news/2024/11/8 19:40:20/文章来源:https://www.cnblogs.com/maihe/p/18533891

这怎么是 *2700???我大受震撼了好吧。

简要题意:有一个初始长度是 \(cnt=1\) 的序列 \(S\),序列每个位置都是若干个二元组 \((p,t)\) 组成的可重集,初始时 \(S_1\) 为空集。\(q\) 组操作(为修改或询问),有如下四种操作:

1 x:把 \(S_x\) 复制到一个新加的点 \(S_{++cnt}\) 上。

2 x p t:将 \((p,t)\) 加入 \(S_x\)

3 x:将 \(S_x\) 最早加入的一个元素删掉。

4 x p:对 \(S_x\) 中所有元素做一个 01 背包(\(p\) 为体积,\(t\) 为价值),限制体积至多为 \(p\),求最大价值。

数据范围:\(1\leq q\leq 3\times 10^4,1\leq p,t\leq 2\times 10^3\)

直接报做法,没遇见过不容易想到。考虑离线之后,把操作树建出来!具体地,我们维护做完每个前三种操作时的 \(time\) 代表相对应的点目前的集合,按这个来建一棵树。比如设 \(lst_x\) 表示最后一次更新 \(S_x\) 的时刻,则 \(2\) 操作相当于 \(lst_x\rightarrow time\) 连一条权值为 \(time\) 的边。\(3\) 操作相当于 ,\(lst_x\rightarrow time\) 连一条 \(-1\)\(1\) 操作相当于 \(lst_x\rightarrow lst_{++cnt}=time\) 连一条权值为 \(0\) 的边。

这棵操作树建出来之后,你就可以把 \(4\) 操作的询问挂在对应的点上,然后做一遍 dfs,维护一个双端队列表示操作,每往下走一条边就 push_back 或 pop_front,回溯时就 pop_back 或 push_front,以及查询当前点的 deque 所有二元组拼起来的几个背包点值。直接做复杂度是 \(O(q^2N)\) 的,其中 \(N=2000\)

怎么优化呢?后面部分也是挺 tricky 的,还是直接报。注意这里背包无法做卷积,只有最后求点值的时候可以保留两个背包然后 \(O(N)\) 拼起来。因此,我们就改为维护两个栈!想象成 "用 stack/数组维护 deque" 的过程,是不是有一个 \(0\) 号点,然后两边相当于分别一个栈来加?如果不删到这个位置,就直接做完了,那么删到了咋办?你会发现,重构的时候把 \(0\) 号点设在非空那个栈的一半处就好了。这样,下次再重构的时候,必须要经过至少 \(O(size)\) 次修改才可以,所以均摊是对的。

具体地,你维护俩 stack 记作 \(SL\)\(SR\),push 直接找到对应栈就好了,pop 如果不影响也直接做,如果影响就把另一个栈从半处分开,重构即可。时间复杂度就变成了优秀的 \(O(qN)\),跑得飞快。

对顶栈(划掉)

一种可能的实现方式:

#include<bits/stdc++.h>
using namespace std;
int p[30005],t[30005],vv[30005];
vector<pair<int,int>>g[30005];
vector<int>wz[30005];
int oo[30005],ans[30005];
const int N=2000;
struct apple{int f[N+5];void jia(int x,int y){for(int i=N-x;i>=0;--i)f[i+x]=max(f[i+x],f[i]+y);}
}e;
deque<pair<int,int>>dq;
stack<apple>sr,sl;
int zr=0,zl=0;
void efront(int p,int t){++zr;auto au=sr.top();au.jia(p,t);sr.emplace(au);
}
void eback(int p,int t){++zl;auto au=sl.top();au.jia(p,t);sl.emplace(au);
}
void pfront(){if(zr>0)--zr,sr.pop();else{int k=zl;while(zl--)sl.pop();zl=0;for(int i=(k+1)/2;i>=2;--i)efront(dq[i-1].first,dq[i-1].second);for(int i=(k+1)/2+1;i<=k;++i)eback(dq[i-1].first,dq[i-1].second);}
}
void pback(){if(zl>0)--zl,sl.pop();else{int k=zr;while(zr--)sr.pop();zr=0;for(int i=k/2;i>=1;--i)efront(dq[i-1].first,dq[i-1].second);for(int i=k/2+1;i<k;++i)eback(dq[i-1].first,dq[i-1].second);}
}
int suan(int p){apple a1=sl.top(),a2=sr.top();int ans=0;for(int i=0;i<=p;++i)ans=max(ans,a1.f[i]+a2.f[p-i]);return ans;
}
void dfs(int x){for(auto z:wz[x]){ans[z]=suan(p[z]);}for(auto pi:g[x]){int cu=pi.first,c2=pi.second;pair<int,int>au(0,0);if(c2>0){eback(p[c2],t[c2]);dq.emplace_back(p[c2],t[c2]);}else if(c2==-1){au=dq.front();pfront();dq.pop_front();}dfs(cu);if(c2>0){pback();dq.pop_back();}else if(c2==-1){efront(au.first,au.second);dq.emplace_front(au);}}
}
int main(){sr.emplace(e);sl.emplace(e);int q;scanf("%d",&q);int z=1;vv[1]=0;for(int te=1;te<=q;++te){int op;scanf("%d",&op);if(op==1){int k=++z,x;scanf("%d",&x);vv[k]=te;g[vv[x]].emplace_back(vv[k],0);}else if(op==2){int x;scanf("%d",&x);scanf("%d%d",&p[te],&t[te]);g[vv[x]].emplace_back(te,te);vv[x]=te;}else if(op==3){int x;scanf("%d",&x);g[vv[x]].emplace_back(te,-1);vv[x]=te;}else{oo[te]=1;int x;scanf("%d%d",&x,&p[te]);wz[vv[x]].emplace_back(te);}}dfs(0);for(int te=1;te<=q;++te)if(oo[te]){printf("%d\n",ans[te]);}return 0;
}

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

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

相关文章

进销存系统是什么?企业如何用好进销存系统?

很多老板都知道,面对激烈的竞争环境,进销存管理已经成为企业运营中不可或缺的一部分。无论是商品的采购、销售,还是库存管理,进销存系统的有效运作都直接影响着企业的资金流动、客户满意度以及市场竞争力。因此,如何高效地应用进销存管理系统,不仅关乎日常运营的顺畅,更…

【linux内核】 BCC Tools命令汇总

什么是BCC Tools 直接通过BPF指令编写BPF 程序是非常繁琐的事情,尤其对于运维人员来说,花70%的时间来编写一个BPF程序来实现一个检查点,不如花70%的时间来熟悉别人已经写好的BPF程序,并且把别人的BPF程序有效的串联起来形成自己分析问题的套路,等有了闲暇时间再去尝试突破…

20222311 2024-2025-1 《网络与系统攻防技术》实验四实验报告

1. 实验内容 1.1恶意代码文件类型标识、脱壳与字符串提取 对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下: (1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具; (2)使用…

进销存系统怎么实施?进销存的实施流程解析

很多老板都知道,企业的日常运营中,进销存管理是至关重要的核心环节之一。它涉及到企业的采购、库存、销售等多个方面,直接影响企业的资金流动、库存控制及客户满意度。因此,如何有效实施进销存管理系统,已成为许多企业提升运营效率、降低成本、优化资源配置的重要任务。 随…

解决centos7.9镜像问题

解决方案 https://wiki.bafangwy.com/doc/719/ 安装chrome(https://www.cnblogs.com/zxqblogrecord/p/13171516.html)时出现以下问题: failure: repodata/repomd.xml from centos7: [Errno 256] No more mirrors to try. http://mirror.centos.org/centos/7/os/x86_64/repodat…

【IDEA】IntelliJ IDEA远程开发:释放本地设备,打破资源与环境的限制

IDEA的远程开发 (Remote Development) 是指在不依赖于本地计算资源的情况下,通过连接远程服务器或虚拟机来进行代码编写、调试和构建的开发模式。这种方式主要通过 JetBrains Gateway 和 JetBrains Projector 提供支持,可以在本地 IDE 界面与远程环境紧密协作,帮助开发者解决…

有哪些免费的轻量级在线 CRM 系统?6款CRM系统盘点

对于许多中小型企业和初创公司而言,如何选择一款既能满足日常需求又具性价比的CRM系统很重要。通常来说,系统的成本是企业选型过程中不可忽视的因素,但在这么多的CRM系统中,各类CRM系统的功能与价格对比真的很容易让人眼花缭乱。 本文将盘6款值得关注的免费轻量级在线CRM系…

[极客大挑战 2019]PHP 1

[极客大挑战 2019]PHP 1 打开文件发现提示信息“备份文件”,查看源码并未发现其他有效信息采用dirsearch爆破目录,找到www.zip文件解压zip,发现是源码泄露提交flag,发现不正确,看到index.php源码中有Get传参,然后反序列化函数unserialize(),判断为反序列化漏洞;查看class…

【IDEA】告别繁琐反编译:IDEA中轻松反编译与修改Jar包

本文带你了解 JarEditor 插件的强大功能,它让你无语再用其他第三方工具,也无需解压 JAR 文件就能直接在IDEA中编辑其中的类和资源文件。还能用它轻松添加、删除或重命名 JAR 包里的文件。即使遇到混淆过的 JAR,JarEditor 也能通过 Javassist 工具搞定。 支持的功能 JarEdito…

[极客大挑战 2019]BuyFlag 1

[极客大挑战 2019]BuyFlag 1 打开实例发现pay.php页面,有提示信息打开源码发现password post提交逻辑burpsuite抓包传参,传入money和password参数,这里password是==弱比较,所以加个字符就可以绕过 password=404a&money=100000000回显发现并没有变化 注意到学生需要CUIT(…

写什么代码来清空缓冲区

在 C++ 中,清空输入缓冲区的方法主要用于清除 std::cin 输入流中的残留字符,避免它们影响后续的输入操作。下面介绍几种常用的办法。 1. cin.ignore() 方法 cin.ignore() 是最常用的清空缓冲区方法,可以忽略输入流中的若干字符。cin.ignore(numeric_limits<streamsize>…