[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 ...
随机推荐
- js字符串转换为数字 总结
a. 将一个字符串转换为数字的一种缺少些技巧但是很清楚明白的方法就是:把Number()构造函数作为一个函数来调用: var number = Number(string_value); b. pa ...
- maven自定义jar到本地仓库
Apache Maven为项目构建提供了绝佳的解决方案,其本地仓库中缓存了远程代理仓库或中央仓库中的资源,从而提高网络资源使用效率,很好很强大! 但是并非所有资源都可以根据GroupId.Artif ...
- JS弹出下载对话框以及实现常见文件类型的下载
写在前面 JS要实现下载功能,一般都是这么几个过程:生成下载的URL,动态创建一个A标签,并将其href指向生成的URL,然后触发A标签的单击事件,这样就会弹出下载对话框,从而实现了一个下载的功能. ...
- 使用C#创建简单的WCF服务
一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(II ...
- jQuery手风琴的制作!!
jQuery手风琴的制作 首先我们先来做一个简单的jQuery的效果图 效果图 如下: css代码 如下: <style type="text/css" media=&quo ...
- Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)
Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...
- Android之RecyclerView入门
首先来实现最简单的列表展示,如图 在这个展示中,RecyclerView的作用仅限于回收和定位屏幕上的TextView,在用户滑动屏幕时,会把上一个视图回收掉,并显示下一个页面的视图,也就是回收再利用 ...
- SSH连不上虚拟机的问题解决
这几天工作任务不重,今早上班打算在liunx下运行下python脚本.打开VM,SSH突然连不上虚拟机了.网上试了很多方法都不行,最后花费2个小时解决了这一问题. 结合我的实际情况,问题解决如下: 1 ...
- 有关Android插件化思考
最近几年移动开发业界兴起了「 插件化技术 」的旋风,各个大厂都推出了自己的插件化框架,各种开源框架都评价自身功能优越性,令人目不暇接.随着公司业务快速发展,项目增多,开发资源却有限,如何能在有限资源内 ...
- MySQL日志文件之错误日志和慢查询日志详解
今天天气又开始变得很热了,虽然很热很浮躁,但是不能不学习,我在北京向各位问好.今天给大家分享一点关于数据库日志方面的东西,因为日志不仅讨厌而且还很重要,在开发中时常免不了与它的亲密接触,就在前几天公司 ...