不想描述了,心累。
兩個操作分別用splay和線段樹來維護
全域性的差值最小直接用splay在插入的時候維護前驅後繼即可
相鄰最小差值我們可以這樣搞
首先 用線段樹維護相鄰的最小值
可以注意到插入元素的操作,如果是在乙個元素之後反覆插入,這些元素之間更新出來的最小值是不會發生改變的。只有元素與元素之間會有不斷的插入而導致最小值變大。所以用線段樹單點修改+維護區間min值,相鄰插入值(中間不會再出現新的數字)之間可以直接暴力維護
我自己手寫的splay還不如set
luogu 1110
#include
#include
#include
#include
#define ll long long
#define il inline
const
int maxm=2100000;
int siz[maxm],cnt[maxm],fa[maxm],ch[maxm][2],data[maxm];
int sz,rt,n,m;
ll date[maxm],minx[maxm<<2],a[maxm],b[maxm];
il ll abs(ll x)
il void update(int x)
il bool get(int x)
il void rotate(int x)
il void splay(int x,int top)
il void splayinsert(ll val)
int now=rt,fax=0;
while(1)
fax=now;
now=ch[fax][data[now]if(!now)
}}il ll splaypre()
il ll splaynext()
il void segbuild(int o,int l,int r)
int mid=(l+r)>>1;
segbuild((o<<1),l,mid),segbuild((o<<1)|1,mid+1,r);
minx[o]=std::min(minx[(o<<1)],minx[(o<<1)|1]);
}il void seginsert(int o,int l,int r,int ind,ll num)
int mid=(l+r)>>1;
if(ind<=mid) seginsert((o<<1),l,mid,ind,num);
else seginsert((o<<1)|1,mid+1,r,ind,num);
minx[o]=std::min(minx[(o<<1)],minx[(o<<1)|1]);
}int main()
a[0]=a[n+1]=1e9+7;
segbuild(1,1,n);
for(int i=1;i<=m;i++)
if(s[4]=='s')
printf("%lld\n",ans1);
if(s[4]=='g')
printf("%lld\n",std::min(ans2,minx[1]));
}return
0;}
ZJOI2007 報表統計
在原數列第 i 個後面新增乙個新元素 k 如果原數列的第 i 個元素已經新增了若干元素,則新增在這些元素的最後。查詢相鄰兩個元素的差值的絕對值的最小值。查詢所有元素中一對元素的差值的絕對值的最小值。第乙個操作很好維護,若要在第 i 個元素後面插值,那麼實際需要插入的位置是 i s i 1 其中 s ...
ZJOI2007 報表統計
題解 一道不錯的模板題 對於第乙個詢問,只需維護乙個支援刪除的堆 方法1.再維護乙個堆,將刪除的數加入這個堆,每次取元素時判斷一下是否和另乙個堆相等 方法2.利用左偏樹可以刪除任意節點 太久不寫都忘了 當然也可以維護一顆平衡樹 對於第二個詢問,只需弄一顆平衡樹求它的前驅後繼就可以了 include ...
ZJOI 2007 報表統計(multiset)
題目鏈結 點我點我 題目描述 q的媽媽是乙個出納,經常需要做一些統計報表的工作。今天是媽媽的生日,小q希望可以幫媽媽分擔一些工作,作為她的生日禮物之一。經過仔細觀察,小q發現統計一張報表實際上是維護乙個非負整數數列,並且進行一些查詢操作。在最開始的時候,有乙個長度為n的整數序列,並且有以下三種操作 ...