BZOJ1058:[ZJOI2007]报表统计(Splay,堆)
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
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP
Sample Output
2
2
1
2
1
HINT
N , M ≤500000 对于所有的数据,序列内的整数不超过5*10^8。
Solution
操作1用splay维护区间
操作2在进行操作1的时候从堆里删除旧的相邻值然后插入两个新的相邻值,
然后在到2的时候输出堆顶
注意可删除堆的操作(将删除的数放到del堆里,当两堆堆顶相同就pop
操作3再开一个splay维护数就好了,每次查询下前驱后继,开个堆维护下最小值
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<queue> 6 #include<algorithm> 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<int,vector<int>,greater<int> >ans; 12 priority_queue<int,vector<int>,greater<int> >del; 13 priority_queue<int,vector<int>,greater<int> >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 else 119 { 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 else 152 { 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 }