博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1058:[ZJOI2007]报表统计(Splay,堆)
阅读量:6254 次
发布时间:2019-06-22

本文共 4690 字,大约阅读时间需要 15 分钟。

Description

  小Q的妈妈是一个出纳,经常需要做一些统计报表的工作。今天是妈妈的生日,小Q希望可以帮妈妈分担一些工
作,作为她的生日礼物之一。经过仔细观察,小Q发现统计一张报表实际上是维护一个可能为负数的整数数列,并
且进行一些查询操作。在最开始的时候,有一个长度为N的整数序列,并且有以下三种操作: INSERT i k 在原数
列的第i个元素后面添加一个新元素k; 如果原数列的第i个元素已经添加了若干元素,则添加在这些元素的最后(
见下面的例子) MIN_GAP 查询相邻两个元素的之间差值(绝对值)的最小值 MIN_SORT_GAP 查询所有元素中最接
近的两个元素的差值(绝对值) 例如一开始的序列为 5 3 1 执行操作INSERT 2 9将得到: 5 3 9 1 此时MIN_GAP
为2,MIN_SORT_GAP为2。 再执行操作INSERT 2 6将得到: 5 3 9 6 1 注意这个时候原序列的第2个元素后面已经
添加了一个9,此时添加的6应加在9的后面。这个时候MIN_GAP为2,MIN_SORT_GAP为1。于是小Q写了一个程序,使
得程序可以自动完成这些操作,但是他发现对于一些大的报表他的程序运行得很慢,你能帮助他改进程序么?

Input

  第一行包含两个整数N,M,分别表示原数列的长度以及操作的次数。第二行为N个整数,为初始序列。接下来
的M行每行一个操作,即“INSERT i k”,“MIN_GAP”,“MIN_SORT_GAP”中的一种(无多余空格或者空行)。

Output

  对于每一个“MIN_GAP”和“MIN_SORT_GAP”命令,输出一行答案即可。

Sample Input

3 5
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP

Sample Output

2
2
1

HINT

N , M ≤500000 对于所有的数据,序列内的整数不超过5*10^8。

Solution

操作1用splay维护区间

操作2在进行操作1的时候从堆里删除旧的相邻值然后插入两个新的相邻值,
然后在到2的时候输出堆顶
注意可删除堆的操作(将删除的数放到del堆里,当两堆堆顶相同就pop
操作3再开一个splay维护数就好了,每次查询下前驱后继,开个堆维护下最小值

Code

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #define N (2000000+1000) 8 using namespace std; 9 int last[N],Val[N],Father[N],Son[N][2],ins[N],Cnt[N],Size[N]; 10 int INF,n,m,a[N],sz=1000000,SZ,ROOT,root; 11 priority_queue
,greater
>ans; 12 priority_queue
,greater
>del; 13 priority_queue
,greater
>minnum; 14 15 int Get(int x){ return Son[Father[x]][1]==x;} 16 void Update(int x){Size[x]=Cnt[x]+Size[Son[x][0]]+Size[Son[x][1]];} 17 int Pre(int now){now=Son[now][0]; while (Son[now][1]) now=Son[now][1]; return now;} 18 int Next(int now){now=Son[now][1]; while (Son[now][0]) now=Son[now][0]; return now;} 19 20 void Rotate(int x) 21 { 22 int wh=Get(x); 23 int fa=Father[x],fafa=Father[fa]; 24 if (fafa) Son[fafa][Son[fafa][1]==fa]=x; 25 Son[fa][wh]=Son[x][wh^1]; Father[fa]=x; 26 if (Son[fa][wh]) Father[Son[fa][wh]]=fa; 27 Son[x][wh^1]=fa; Father[x]=fafa; 28 Update(fa); Update(x); 29 } 30 31 void Splay(int x,int tar,int &Root) 32 { 33 for (int fa; (fa=Father[x])!=tar; Rotate(x)) 34 if (Father[fa]!=tar) 35 Rotate(Get(fa)==Get(x)?fa:x); 36 if (!tar) Root=x; 37 } 38 39 void Insert(int x) 40 { 41 if (!root) 42 { 43 root=++sz; 44 Size[sz]=Cnt[sz]=1; 45 Val[sz]=x; 46 return; 47 } 48 int now=root,fa=0; 49 while (1) 50 { 51 if (x==Val[now]) 52 { 53 Cnt[now]++; 54 Update(now); 55 Splay(now,0,root); 56 return; 57 } 58 fa=now,now=Son[now][x>Val[now]]; 59 if (now==0) 60 { 61 Size[++sz]=Cnt[sz]=1; 62 Val[sz]=x; 63 Father[sz]=fa; 64 Son[fa][x>Val[fa]]=sz; 65 Splay(sz,0,root); 66 return; 67 } 68 } 69 } 70 71 int Build(int l,int r,int fa) 72 { 73 if (l>r) return 0; 74 int mid=(l+r)>>1; 75 Size[mid]=Cnt[mid]=1; 76 Val[mid]=a[mid]; 77 Father[mid]=fa; 78 Son[mid][0]=Build(l,mid-1,mid); 79 Son[mid][1]=Build(mid+1,r,mid); 80 return mid; 81 82 } 83 int Findx(int x) 84 { 85 int now=ROOT; 86 while (1) 87 if (x<=Size[Son[now][0]]) 88 now=Son[now][0]; 89 else 90 { 91 x-=Size[Son[now][0]]; 92 if (x<=Cnt[now]) 93 { 94 Splay(now,0,ROOT); 95 return now; 96 } 97 x-=Cnt[now]; 98 now=Son[now][1]; 99 }100 }101 int Split(int x,int y)102 {103 Splay(x,0,ROOT); Splay(y,x,ROOT);104 return y;105 }106 107 int main()108 {109 memset(&INF,0x3f,sizeof(INF));110 scanf("%d%d",&n,&m); SZ=n+5;111 for (int i=1;i<=n;++i)112 scanf("%d",&a[i+1]);113 a[1]=a[n+2]=INF;114 for (int i=1;i<=n+2;++i)115 {116 Insert(a[i]);117 if (Cnt[root]>1 && Val[root]!=INF) minnum.push(0);118 else119 { 120 int pre=Pre(root),next=Next(root);121 if (pre) minnum.push(abs(Val[root]-Val[pre]));122 if (next) minnum.push(abs(Val[root]-Val[next]));123 }124 if (i>1) ans.push(abs(a[i]-a[i-1]));125 last[i]=i;126 }127 ROOT=Build(1,n+2,0);128 sort(a+1,a+n+2+1);129 for (int i=3;i<=n+1;++i)130 minnum.push(abs(Val[i]-Val[i-1]));131 for (int i=1;i<=m;++i)132 {133 char opt[10]; int x,y;134 scanf("%s",opt);135 if (opt[4]=='R')136 {137 scanf("%d%d",&x,&y); x++;138 int p=Split(last[x],x+1);139 Val[++SZ]=y; Father[SZ]=p;140 Son[p][0]=SZ;141 ins[x]++;142 Size[SZ]=Cnt[SZ]=1;143 Splay(SZ,0,ROOT);144 last[x]=SZ;145 int pre=Pre(ROOT),next=Next(ROOT);146 del.push(abs(Val[pre]-Val[next]));147 ans.push(abs(Val[pre]-Val[SZ]));148 ans.push(abs(Val[next]-Val[SZ]));149 Insert(y);150 if (Cnt[root]>1) minnum.push(0);151 else152 { 153 pre=Pre(root),next=Next(root);154 minnum.push(abs(Val[root]-Val[pre]));155 minnum.push(abs(Val[root]-Val[next]));156 }157 }158 if (opt[4]=='G')159 {160 while (!del.empty() && del.top()==ans.top())161 del.pop(),ans.pop();162 printf("%d\n",ans.top());163 }164 if (opt[4]=='S')165 printf("%d\n",minnum.top());166 }167 }

转载于:https://www.cnblogs.com/refun/p/8685636.html

你可能感兴趣的文章
阿里、腾讯内部十二个大数据项目,你都有做过吗?
查看>>
3 无穷大和无穷小
查看>>
(笔记)响应式布局
查看>>
redis系列5---底层数据结构之链表
查看>>
如何基于 Docker 在服务器上部署 Seafile Community 版本
查看>>
老板让我十分钟上手开发vue-element-admin
查看>>
mybatis基础学习(二)
查看>>
经典SQL语句大全
查看>>
Size转换工具类
查看>>
Mac控制台的渐变色玩一下!
查看>>
【C】自己写一个程序实现memcpy功能
查看>>
java微服务 k8s生产环境搭建
查看>>
go语言入门教程百度网盘:椭圆曲线加密算法ECC和椭圆曲线数字签名算法ECDSA
查看>>
使用Nginx搭建网页服务器
查看>>
大部分程序员都在抱怨自己工资低,但是真的工资低吗?
查看>>
Android 音视频开发 - 使用Camera采集视频
查看>>
探索iOS中Block的实现原理
查看>>
记录一次线上OOM情况排查过程
查看>>
91 Decode Ways
查看>>
工作中遇到的问题
查看>>