[BZOJ 1058][ZJOI 2007]报表统计 平衡树+线段树
考试的时候看见这道题,感觉自己能AC掉,然后就冲着正解去了。然后想了想数据结构,应该是平衡树。然而蒟蒻的我忘了平衡树怎么打了。。然后就根据自己的记忆和理解打了出来。然后我简单的以为相邻的用个链表就能解决。没想到gg了。因为插一个的时候多出来两个相邻差值,然后会删除掉原来的一个相邻差值。这下我就懵逼了。想了想我能用的数据结构,好像没有什么思路,然后就用了个优先队列。挂掉了。
其实全局差值最小比较好求,用平衡树求一个前驱(<=它的最大值)和后继(>=它的最小值)即可。
然后相邻差值,可以用线段树维护,以个数为下标,存的是差值。新差值的下标为n+i即可。因为我们要更新之后,直接查询总共的最小值,所以顺序不用管。
注意到的是,在插入一个数后,会使原来的差值消除,产生两个新的差值,不需要删除,只需一个替换掉原来的,一个在尾部插入。用last[]记录原位置最后一个数,fir[]记录原位置第一个数,再用id[]记录最后一个数的位置,方便替换。
例如数列 1 3 5 2 7
线段树储存 2 2 3 5
当在1 3之间插入5时,新产生差值4 覆盖2,在末尾插入新差值2
线段树储存 4 2 3 5 2
#include<cstdio> #include<algorithm> #include<queue> #include<iostream> #include<cstring> #include<cstdlib> using namespace std; #define N 401000 #define inf 0x7fffffff #define pos(i,a,b) for(int i=(a);i<=(b);i++) int n,m; int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f; } struct xixi{ int l,r,num; }t[N]; struct haha{ int l,r,rnd,num; }tree[N]; int root,size; void rturn(int &k){ int t=tree[k].l; tree[k].l=tree[t].r; tree[t].r=k; k=t; } void lturn(int &k){ int t=tree[k].r; tree[k].r=tree[t].l; tree[t].l=k; k=t; } void insert(int &k,int x){ if(k==0){ k=++size; tree[k].rnd=rand(); tree[k].num=x; } if(x>tree[k].num){ insert(tree[k].r,x); if(tree[tree[k].r].rnd<tree[k].rnd) lturn(k); } if(x<tree[k].num){ insert(tree[k].l,x); if(tree[tree[k].l].rnd<tree[k].rnd) rturn(k); } } int pro=inf,sub=inf; void query_pro(int &k,int num){ if(k==0) return; if(num>tree[k].num){ pro=tree[k].num; query_pro(tree[k].r,num); } else{ if(num==tree[k].num){ pro=tree[k].num; } else{ query_pro(tree[k].l,num); } } } void query_sub(int &k,int num){ if(k==0) return; if(num<tree[k].num){ sub=tree[k].num; query_sub(tree[k].l,num); } else{ if(num==tree[k].num){ sub=tree[k].num; } else{ query_sub(tree[k].r,num); } } } int ans3=inf; int aabs(int x){ if(x<0) return -x; return x; } void build(int l,int r,int k){ t[k].l=l; t[k].r=r; if(l==r){ t[k].num=inf; return; } int mid=(l+r)>>1; build(l,mid,k*2); build(mid+1,r,k*2+1); } void change(int pos,int num,int k){ if(t[k].l==t[k].r){ t[k].num=num; return; } if(pos<=t[k*2].r){ change(pos,num,k*2); } else{ change(pos,num,k*2+1); } t[k].num=min(t[k*2].num,t[k*2+1].num); } int query(int l,int r,int k){ if(t[k].l==l&&t[k].r==r){ return t[k].num; } int mid=(t[k].l+t[k].r)>>1; if(r<=mid){ return query(l,r,k*2); } else{ if(l>mid) return query(l,r,k*2+1); else return min(query(l,mid,k*2),query(mid+1,r,k*2+1)); } } int id[N],ji,last[N],fir[N]; int main(){ //freopen("love.in","r",stdin); //freopen("love.out","w",stdout); n=read();m=read(); build(0,n+m-1,1); pos(i,1,n){ int x=read(); fir[i]=x;last[i]=x; query_pro(root,x); query_sub(root,x); int temp=min(aabs(x-pro),aabs(x-sub)); ans3=min(ans3,temp); insert(root,x); } pos(i,1,n-1){ int temp=aabs(fir[i]-fir[i+1]); id[i]=++ji; change(ji,temp,1); } pos(i,1,m){ char s[50]; scanf("%s",s); if(s[4]=='G'){ printf("%d\n",query(0,ji,1)); } if(s[4]=='S'){ printf("%d\n",ans3); } if(s[4]=='R'){ int x=read(),y=read(); query_pro(root,y); query_sub(root,y); int temp=min(aabs(y-pro),aabs(y-sub)); ans3=min(ans3,temp); insert(root,y); if(x!=n){ int b=aabs(last[x]-y),c=aabs(y-fir[x+1]); //cout<<"b="<<b<<" c="<<c<<endl; change(id[x],b,1); last[x]=y; id[x]=++ji; change(id[x],c,1); } if(x==n){ int b=aabs(last[x]-y); id[x]=++ji; change(id[x],b,1); } } } //pos(i,1,n) //cout<<id[i]<<endl; //pos(i,1,ji){ //cout<<"query="<<query(0,4,1)<<endl; //} return 0; }
[BZOJ 1058][ZJOI 2007]报表统计 平衡树+线段树的更多相关文章
- BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)
题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- 【BZOJ 3196】二逼平衡树 线段树套splay 模板题
我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...
- bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...
- BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)
LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)
BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...
- 3682: Phorni 后缀平衡树 线段树
国际惯例的题面: 考虑如果没有强制在线我们能怎么水掉这个题,先构造出字符串,各种方法求一下后缀数组,然后线段树维护区间rank最小的位置即可.然而他要求强制在线,支持插入后缀,并比较后缀大小(求ran ...
随机推荐
- iOS 实现简单的毛玻璃效果
最近在整理导航栏的渐隐渐现效果,整理过程中偶然学会了图片的毛玻璃效果实现,很简单,不多说了,先上图看看效果对比, 这是原图, 这是加了效果后的,创建图片的代码就不上了,下面看下添加效果的代码: // ...
- Angular 4 学习笔记 从入门到实战 打造在线竞拍网站 基础知识 快速入门 个人感悟
最近搞到手了一部Angular4的视频教程,这几天正好有时间变学了一下,可以用来做一些前后端分离的网站,也可以直接去打包web app. 环境&版本信息声明 运行ng -v @angular/ ...
- 简单RPC框架-业务线程池
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- cygwin和ffmpeg的两三事
cygwin和ffmpeg的下载地址: https://cygwin.com/install.html http://www.ffmpeg.org/download.html 标题看上去有些无厘头,然 ...
- centos6.5下redis安装步骤总结
1.首先下载一个版本 我用的是3.2.9 解压:tar -zxvf /redis-stable.tar.gz 在/usr/local/新建redis文件夹 然后把解压好的文件夹移动到/usr/loca ...
- mysql数据库左联的使用(一张数据库表关联到另外一张数据库表)
左联的数据库表,然后显示的在页面显示的jsp里面改一下代理种类ID的name,这样在页面上显示的不是id了,而是变成你修改了以后相对于的name了
- 前端页面——Cookie与Session有什么区别
我们在实际生活中总会遇到这样的事情,我们一旦登录(首次输入用户名和密码)某个网站之后,当我们再次访问的时候(只要不关闭浏览器),无需再次登录.而当我们在这个网站浏览一段时间后,它会产生我们浏览的记录, ...
- Xcode导出App一般问题及其解决方法(开发者协议变更及Bundle Id过期问题)
Xcode导出App一般问题及其解决方法 问题一:开发者协议变更问题. 变更后打包会出现如下图A警告,此时点击 "visit developer website"进入Apple开发 ...
- JavaScript中的设计模式:单例模式
定义 单例模式就是一个类只能实例化一个对象,并且提供了一个访问它的全局访问点. 一般在实现登陆框,或者一个全局的控制器都会用到单例模式.现实中有window对象,线程池,全局缓存等. 简单实现 var ...
- 浅谈JVM与内存分配
一.程序内存分配 初始内存分配 当一个程序准备运行时,它首先向java虚拟机要内存,但是java虚拟机本身没有权限,它只能向操作系统申请内存,此时java虚拟机会拥有一个初始内存, 此处额外说明一下e ...