题解 Luogu P1110 【[ZJOI2007]报表统计】
感谢 @cmy962085349 提供的hack数据,已经改对了。
先声明,我好像是题解里写双$fhq$ $treap$里唯一能过的...(最后两个点啊)
思路:首先看题目,$MIN_GAP_SORT$ 明显是求它的前驱与后继(可能有相同的),所以就用平衡树,但是又要求两个相邻的数的差,就可以有再开一个平衡树存放差值
实现:抛开奇奇怪怪的的题面,主要考虑这三个操作:
1、$INSERT$ $i$ $k$:
这个很简单,用链表就行了(数组模拟的),但是要注意,插入的时候,要接着上一个在这插入的,还要做双向链表,数组要记得开两倍
最重要的是,插入了以后,这个数的前一个数与后一个数的差要在存放相邻两个数的差的$fhq$ $treap$里删除,并插入这个数与前一个数的差和这个数与后一个数的差要存进去
2、$MIN_GAP$:
做完插入,就在存差的$fhq$ $treap$查$rank$$1$好了(最左边的那个节点)
3、$MIN_SORT_GAP$:
为了避免查前驱与后继时出现自己(不是另一个与自己相同的数),所以插入时(分裂后,合并前,这样正好符合查前驱与后继的标准)就比较取小,询问时直接输出就好了
P.S. 似乎经过 @cmy962085349 的 $hack$ 数据更正以后,似乎并不需要过于卡常了(原来代码需要疯狂卡常)(说明题解里双平衡树还是因为写错了而 $Tle$ 了后面两个点),似乎不用 $cin$ 与 $cout$ 就能过,不需要加什么 $register$ 了(虽然我还是加了)
附上AC代码:
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<iostream>
using namespace std; struct tree{//存每个值的数(不是差)
int size,val,dat,l,r;
}tr[1000005];//数组记得开两倍 int s_tr,root,n,m,x,y,z,a[1000005],b[1000005],c[1000005]; int min_sort_gap;//MIN_SORT_GAP的答案 inline int abs(int a){
return a<0?-a:a;
} inline int min(int a,int b){
return a<b?a:b;
} //fhq treap常规操作 inline int new_tr(int val){
tr[++s_tr].val=val;
tr[s_tr].size=1;
tr[s_tr].dat=rand();
return s_tr;
} inline void update(int p){
tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;
} void split(int p,int k,int &x,int &y){
if(!p){
x=y=0;
return;
}
if(tr[p].val<=k)x=p,split(tr[p].r,k,tr[p].r,y);
else y=p,split(tr[p].l,k,x,tr[p].l);
update(p);
} int merge(int x,int y){
if(!x||!y)return x+y;
if(tr[x].dat>tr[y].dat){
tr[x].r=merge(tr[x].r,y);
update(x);
return x;
}
else {
tr[y].l=merge(x,tr[y].l);
update(y);
return y;
}
} inline int Max(int x){//一棵fhq(可能是分裂后)中最大的
while(tr[x].r)x=tr[x].r;
return tr[x].val;
} inline int Min(int y){//一棵fhq(可能是分裂后)中最大的
while(tr[y].l)y=tr[y].l;
return tr[y].val;
} inline void insert(int val){
split(root,val,x,y);
if(tr[x].size)//要有才行
min_sort_gap=min(min_sort_gap,abs(val-Max(x)));
if(tr[y].size)//要有才行
min_sort_gap=min(min_sort_gap,abs(Min(y)-val));
root=merge(merge(x,new_tr(val)),y);
} //存差值的fhq treap struct tree1{
int size,val,dat,l,r;
}tr1[1000005]; int s_tr1,root1; inline int new_tr1(int val){
tr1[++s_tr1].val=val;
tr1[s_tr1].size=1;
tr1[s_tr1].dat=rand();
return s_tr1;
} inline void update1(int p){
tr1[p].size=tr1[tr1[p].l].size+tr1[tr1[p].r].size+1;
} void split1(int p,int k,int &x,int &y){
if(!p){
x=y=0;
return;
}
if(tr1[p].val<=k)x=p,split1(tr1[p].r,k,tr1[p].r,y);
else y=p,split1(tr1[p].l,k,x,tr1[p].l);
update1(p);
} int merge1(int x,int y){
if(!x||!y)return x+y;
if(tr1[x].dat>tr1[y].dat){
tr1[x].r=merge1(tr1[x].r,y);
update1(x);
return x;
}
else {
tr1[y].l=merge1(x,tr1[y].l);
update1(y);
return y;
}
} inline void insert1(int val){
split1(root1,val,x,y);
root1=merge1(merge1(x,new_tr1(val)),y);
} inline void delete_val(int val){//这棵fhq要能支持删除
split1(root1,val,x,z);
split1(x,val-1,x,y);
y=merge1(tr1[y].l,tr1[y].r);
root1=merge1(merge1(x,y),z);
} inline int Min1(int y){
while(tr1[y].l)y=tr1[y].l;
return tr1[y].val;
} char s[101];//卡常 inline int read(){//卡常
int r=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')r=(r<<1)+(r<<3)+c-'0',c=getchar();
return r*f;
} int main(){
srand(time(0));
n=read(),m=read();
min_sort_gap=1e9+10;
for(register int i=1;i<=n;i++){//卡常
a[i]=read();
insert(a[i]);
}
for(register int i=1;i<n;i++)//卡常减少if
insert1(abs(a[i+1]-a[i])),c[i]=i+1;
for(register int i=2;i<=n;i++)//卡常减少if,n+1是因为可能在第n个后面插入
b[i]=i-1;
b[n+1]=n;
int cnt=n;
for(register int i=1;i<=m;i++){//卡常
scanf("%s",s);
if(s[0]=='I'){
int j=read(),k=read();
delete_val(abs(a[j+1]-a[b[j+1]]));//因为插入后不在一起了,删除
insert1(abs(a[b[j+1]]-k));//插入后多了两个差值(不算删除的)
if(j<n)insert1(abs(k-a[j+1]));//可能插在第n个的后面
a[++cnt]=k;//放进数组,这件事一定要在上述操作以后做,不然若连续插入在第n个数以后就挂了,因为第一次cnt+1后会直接取代n+1,b[n+1]也就没什么用了
b[cnt]=b[j+1];//数组模拟链表
c[cnt]=j+1;
c[b[j+1]]=cnt;//记得修改前一个与后一个的指向
b[j+1]=cnt;
insert(k);
}
else {
if(s[4]=='G')printf("%d\n",Min1(root1));//整棵fhq里最小的
else printf("%d\n",min_sort_gap);
}
}
return 0;
}
再次感谢 @cmy962085349
完结偷偷撒花!(✿✿ヽ(°▽°)ノ✿)
题解 Luogu P1110 【[ZJOI2007]报表统计】的更多相关文章
- Luogu P1110 [ZJOI2007]报表统计 multiset
沿用了学长的$multiset$ 然后这道题可以看到我的程序中有两行注释,它在我看来和他们下面的代码没区别,但是我们发现,C++会先调用后面的参数,所以$--it$会被先执行 ... ... ... ...
- 洛谷 P1110 [ZJOI2007]报表统计 解题报告
P1110 [ZJOI2007]报表统计 题目描述 \(Q\)的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小\(Q\)希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细 ...
- P1110 [ZJOI2007]报表统计
题目描述 Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细观察,小Q发现统计一张报表实际上是维护一个非负整数数列,并 ...
- P1110 [ZJOI2007]报表统计 (multiset)
[题目链接] https://www.luogu.org/problemnew/show/P1110 有以下三种操作: INSERT i k:在原数列的第i个元素后面添加一个新元素k:如果原数列的第i ...
- 2018.11.09 洛谷P1110 [ZJOI2007]报表统计(multiset)
传送门 sb题. 直接用两个multisetmultisetmultiset维护相邻两个数的差值和所有数的前驱后继. 插入一个数的时候更新一下就行了. 代码: #include<bits/std ...
- bzoj P1058 [ZJOI2007]报表统计——solution
1058: [ZJOI2007]报表统计 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 4099 Solved: 1390 [Submit][St ...
- 【BZOJ1058】[ZJOI2007]报表统计 STL
[BZOJ1058][ZJOI2007]报表统计 Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一.经 ...
- [ZJOI2007]报表统计(splay,堆)
[ZJOI2007]报表统计(luogu) Description 题目描述 Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. ...
- bzoj1058: [ZJOI2007]报表统计
set.操作:insert(u,v)在u后面插入v,若u后面已插入过,在插入过的后面插入.mingap求出序列两两之间差值的最小值.minsortgap求出排序后的序列两两之间的最小值.用multis ...
- BZOJ 1058: [ZJOI2007]报表统计( 链表 + set )
这种题用数据结构怎么写都能AC吧...按1~N弄个链表然后每次插入时就更新答案, 用set维护就可以了... --------------------------------------------- ...
随机推荐
- ICEM-轴
https://yunpan.cn/cuy98EwwXvYkb 访问密码 0897
- ubuntu之路——day10.6 如何理解人类表现和超过人类表现
从某种角度来说,已知的人类最佳表现其实可以被当做贝叶斯最优错误,对于医学图像分类可以参见下图中的例子. 那么如何理解超过人类表现,在哪些领域机器已经做到了超越人类呢?
- Qt--core模块概述
QtCore模块是所有其它Qt模块的基础,包含以下核心功能: Qt Data Types:数据类型Qt Object Model:对象模型(包括元对象模型.属性系统.信号与槽机制.对象树)Input/ ...
- 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析
漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 - FreeBuf互联网安全新媒体平台 https: ...
- setInterval调用ajax回调函数不执行的问题
setInterval调用ajax回调函数不执行 1.首先检查你的setInterval()函数写法是否正确 参考写法 // 检查是否支付成功 var isPayRequest=false; var ...
- SeetaFace2 cmake VS2015编译编译
cmake Selecting Windows SDK version 10.0.17134.0 to target Windows 10.0.18362. == BUILD_VERSION: v2. ...
- linux配置docker报错:ImportError: No module named yum
如题,安装docker后配置仓库报错: [root@centos ~]# yum-config-manager --add-repo https://download.docker.com/linux ...
- no match for call to ‘(std::__cxx11::string {aka std::__cxx11::basic_string
问题: t->package().ship_id(sqlRow[1]);其中 ship_id为 结构体package中的string类型.如下: typedef struct Package{ ...
- django ORM 自定义字段
class FixedCharField(models.Field): """ 自定义的char类型的字段类 """ def __init_ ...
- Spring cloud微服务安全实战-3-2 第一个API及注入攻击防护
先来写一些用户的基础数据的管理的api.就是用户的基本的增删改查.用spring boot可以很容易的写出这种api 首先新建maven的项目 依赖关系 引入依赖.用最新的spring boot ht ...