P1110 [ZJOI2007] 报表统计

news/2025/1/16 18:45:06/文章来源:https://www.cnblogs.com/LG017/p/18675590

P1110 [ZJOI2007] 报表统计

题目描述

小 Q 的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小 Q 希望可以帮妈妈分担一些工作,作为她的生日礼物之一。

经过仔细观察,小 Q 发现统计一张报表实际上是维护一个非负整数数列,并且进行一些查询操作。

在最开始的时候,有一个长度为 \(n\) 的整数序列 \(a\),并且有以下三种操作:

  • INSERT i k:在原数列的第 \(i\) 个元素后面添加一个新元素 \(k\);如果原数列的第 \(i\) 个元素已经添加了若干元素,则添加在这些元素的最后(见样例说明)。
  • MIN_GAP:查询相邻两个元素的之间差值(绝对值)的最小值。
  • MIN_SORT_GAP:查询所有元素中最接近的两个元素的差值(绝对值)。

于是小 Q 写了一个程序,使得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

数据规模与约定

对于全部的测试点,保证 \(2 \le n, m \le 5\times10^5\)\(1 \leq i \leq n\)\(0 \leq a_i, k \leq 5 \times 10^8\)

说句闲话

又是一道在压在List里很久的题 (然后你就一直拖到现在才写是吧)

Solution:

不难发现,INSERT i k 简直是平衡树模板, MIN_SORT_GAP 显然是单调不升的一个东西,我们只需要在 INSERT i k 时维护一下 \(k\) 和左右邻居产生的贡献就好了。所以这题唯一不太好写的就是这个 MIN_GAP

所以我们再维护两个值,\(pre,suf\) 分别表示当前节点的子树下编号最小/最大的节点所对应的权值。那么“与x相邻”的两个树就分别是:\(t[ls].suf\),\(t[rs].pre\)。我们只需要在 pushup 的时候维护这两个东西对于节点 \(x\) 的贡献就好了。

一些细节:

由于我们的\(pre,suf\) 都不是永久化的,所以在每一次 pushup 时要先将当前节点的 \(suf,pre\) 重新赋值为 \(t[x].val\) 然后更新,否则正确性就是错的。

Code:

#include<bits/stdc++.h>
const int N=1.1e6+5;
const int inf=1e9;
using namespace std;
int n,m,flag;
int rd(){return rand()*rand()+17;}
struct FHQ_Treap{int cnt=0,rt;struct Tree{int ls,rs,val,siz,pre,suf,ans,pri;}t[N];int Node(int val){t[++cnt]={0,0,val,1,val,val,inf,rd()};return cnt;}inline void pushup(int x){int ls=t[x].ls,rs=t[x].rs;t[x].siz=t[ls].siz+t[rs].siz+1;t[x].suf=t[x].pre=t[x].val;if(ls)t[x].pre=t[ls].pre;if(rs)t[x].suf=t[rs].suf;t[x].ans=inf;if(ls)t[x].ans=min({abs(t[ls].suf-t[x].val),t[ls].ans,t[x].ans});if(rs)t[x].ans=min({abs(t[rs].pre-t[x].val),t[rs].ans,t[x].ans});}void splite_siz(int x,int &a,int &b,int k){if(!x){a=b=0;return ;}int tmp=t[t[x].ls].siz+1;if(k>=tmp){a=x;splite_siz(t[x].rs,t[x].rs,b,k-tmp);}else {b=x;splite_siz(t[x].ls,a,t[x].ls,k);}pushup(x);}void splite_val(int x,int &a,int &b,int k){if(!x){a=b=0;return ;}if(k>=t[x].val){a=x;splite_val(t[x].rs,t[x].rs,b,k);}else {b=x;splite_val(t[x].ls,a,t[x].ls,k);}pushup(x);}int merge(int x,int y){if(!x||!y)return x|y;if(t[x].pri<t[y].pri){t[x].rs=merge(t[x].rs,y);pushup(x);return x;}else {t[y].ls=merge(x,t[y].ls);pushup(y);return y;}}
}T1,T2;
struct Segment_Tree{#define ls x<<1#define rs x<<1|1struct Tree{int cnt;}t[N];void build(int x,int l,int r){t[x].cnt=r-l+1;if(l==r)return;int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);}void upd(int x,int l,int r,int pos){t[x].cnt++;if(l==r)return;int mid=l+r>>1;if(pos<=mid)upd(ls,l,mid,pos);if(mid<pos)upd(rs,mid+1,r,pos);}int query(int x,int l,int r,int L,int R){if(L<=l&&r<=R)return t[x].cnt;int mid=l+r>>1,res=0;if(L<=mid)res+=query(ls,l,mid,L,R);if(mid<R)res+=query(rs,mid+1,r,L,R);return res;}#undef ls#undef rs
}T;
int ans[2]={inf,inf};
void check(int x)
{int a,b,c;T1.splite_siz(T1.rt,a,b,x);T1.splite_siz(b,b,c,1);cout<<T1.t[b].val<<"\n";T1.rt=T1.merge(T1.merge(a,b),c);
}
void debug()
{for(int i=0;i<T1.cnt;i++)check(i);cout<<"\n";
}
void insert(int pos,int val)
{int a,b,c,d;a=b=c=d=0;T1.splite_siz(T1.rt,a,c,pos);T1.rt=T1.merge(T1.merge(a,T1.Node(val)),c);ans[0]=T1.t[T1.rt].ans;a=b=c=d=0;T2.splite_val(T2.rt,a,c,val);T2.splite_siz(a,a,b,T2.t[a].siz-1);T2.splite_siz(c,c,d,1);if(b)ans[1]=min(ans[1],abs(T2.t[b].val-val));if(c)ans[1]=min(ans[1],abs(T2.t[c].val-val));T2.rt=T2.merge(T2.merge(T2.merge(a,b),T2.Node(val)),T2.merge(c,d));
}
char c[20];
void work()
{cin>>n>>m;for(int i=1,x;i<=n;i++){scanf("%d",&x);insert(i-1,x);}T.build(1,1,n);for(int i=1,pos,val,tot;i<=m;i++){scanf("%s",c);if(c[0]=='I'){scanf("%d%d",&pos,&val);tot=T.query(1,1,n,1,pos);insert(tot,val);T.upd(1,1,n,pos);}if(c[4]=='G'){printf("%d\n",T1.t[T1.rt].ans);}if(c[4]=='S'){printf("%d\n",ans[1]);}}
}
int main()
{//freopen("P1110_1.in","r",stdin);freopen("P1110.out","w",stdout);work();return 0;
}

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

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

相关文章

28. 事件处理

一、事件与事件处理 1.1、什么是事件事件是程序收到外界的输入,处于某种状态时自动发送的信号。事件有固定的类型,每种类型有自己的处理函数,用户只要重写这些函数,即可达到特定的目的。通过事件可以用一个控件监测另外一个控件,并可过滤被监测控件发出的事件。可视化应用…

2025上半年

孩子们,正睿补习计划重启了。 自建题单:ZR 2022 summer B - Virtual Judge P10447 最短 Hamilton 路径 - 洛谷 | 计算机科学教育新生态 求从 \(1\) 号点出发恰好经过每个点一次并且最终回到 \(1\) 号点的最短路径。 设 \(dp_{i,s}\) 表示恰好经过了集合 \(s\) 中的点一次,当…

Agent FFT

Agent FFT请你根据 https://www.cnblogs.com/CDOI-24374/p/17733240.html 这篇文章,仿照写一个好的,以下是一篇仿照《Azune FFT》风格的文章: Azune FFT:异界之战 可能是 Azune 童话系列。感谢 int_R 提供灵感与素材,让奇幻之光照亮一切! ——题记 「报告,INQ。已抵达 …

2025/1/16

今天继续学习了Android开发的相关知识,做手机端的app今天学的是用xml文件控制页面,类似javaweb里面的前端,有许多标签,还解决了运行卡退的一个小问题,需要定义一个主题。

CICD Day9、Argo CD增强持续交付

1、Argo CD简介在Jenkins CI/CD流程中的持续交付阶段,既部署到k8s集群阶段,使用kubectl工具来进行应用程序的部署和更新操作,但这种方式无法实时跟踪应用程序的状态。这将造成用户在CI/CD流程完成后需要额外操作kubernetes集群,以进一步查看应用程序的状态。为了解决这些问…

专为高性能计算和低功耗应用设计的MPF100T-1FCVG484E MPF100TL-FCSG325E MPF100TL-FCVG484I PolarFire FPGA产品系列

‌MPF100TL-FCG484E PolarFire FPGA是Microchip推出的一款高性能、低功耗的FPGA产品系列,特别适用于各种需要高性能计算和低功耗的应用场景‌。‌PolarFire FPGA是Microchip推出的一款高性能、低功耗的FPGA产品系列,特别适用于各种需要高性能计算和低功耗的应用场景‌。这些器…

wordpress 从服务器收到预料之外的响应。此文件可能已被成功上传。请检查媒体库或刷新本页。此响应不是合法的JSON响应。解决方法.210721

两种报错方式: 1.此响应不是合法的JSON响应。 2.从服务器收到预料之外的响应。此文件可能已被成功上传。请检查媒体库或刷新本页。 情况:媒体服务器上传小文件没问题,大一点的文件报这个错误。 原因:这是因为nginx限制了请求体大小 方案:需要在nginx的虚拟机配置文件中添加…

docker containner挂掉,无法exec进入bash,如何修改文件的终极解决方法.210730

场景: Nginx在bash里面配置的时候挂掉了,然后docker start不起来,exec bash进不去,造成无法再改里面的文件了 解决方法: 1,docker ps –a 可以查到所有docker,包括没有运行的,找到containner ID [root@hecs-29489 ~]# docker ps -a CONTAINER ID IMAGE COMMAND…

HP惠普笔记本重装系统无法引导无法进操作系统的终极解决方法.210804

F9进入BIOS-先进(Advanced)-安全引导配置- 启用传统支持和禁用安全引导.zstitle { width: 280px; text-align: center; font-size: 26px } .zsimgweixin { width: 280px } .zsimgali { width: 280px; padding: 0px 0px 50px 0px } .zsleft { float: left } .zsdiv { display:…

Feign与SpringCloud LoadBalancer实现负载均衡源码分析

SpringCloud LoadBalancer 众所周知,SpringCloud体系中负载均衡的组件有SpringCloud LoadBalancer和Ribbon,Ribbon也在逐渐的被替代掉,因为SpringCloud LoadBalancer性能更高,支持响应式 下面通过hard-coded体现一下SpringCloud的负载均衡 首先有一个【say-hello】服务,提…

JS — 判断语句与循环语句

js的判断语句与循环语句...(* ̄0 ̄)ノ判断语句JavaScript中的if-else语句与C++、Python、Java中类似。直接输出到控制台:test.html中的内容为: <script type="module">let score = 90;if (score >= 85) {console.log("A");} else if (score &g…

Living-Dream 系列笔记 第92期

最小路径点覆盖 在一张 DAG 上,求一个路径的集合,使得它们两两不相交,且覆盖所有的点。 结论:答案即为 \(总点数-最大匹配\)(于是 \(总点数-最大匹配=总点数-最小点覆盖=最大独立集=最大团=最小路径点覆盖\))。 证明: 不妨转换角度,从研究路径转为研究点。 因为路径两两…