ZJOI2007 報表統計

2021-08-16 19:30:44 字數 1615 閱讀 1265

不想描述了,心累。

兩個操作分別用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的整數序列,並且有以下三種操作 ...