1. 程式人生 > >1058. [ZJOI2007]報表統計【平衡樹-splay+堆】

1058. [ZJOI2007]報表統計【平衡樹-splay+堆】

++ insert pop sizeof tar output span body for

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。

操作1用splay維護區間
操作2在進行操作1的時候從堆裏刪除舊的相鄰值然後插入兩個新的相鄰值,
然後在到2的時候輸出堆頂
註意可刪除堆的操作(將刪除的數放到del堆裏,當兩堆堆頂相同就pop
操作3再開一個splay維護數就好了,每次查詢下前驅後繼,開個堆維護下最小值

  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 }

1058. [ZJOI2007]報表統計【平衡樹-splay+堆】