luogu1110 ZJOI2007 報表統計

2022-03-01 05:12:29 字數 1451 閱讀 6724

這裡的初始化就不講了,看完操作講解就應該明白了,再不行就去看**

對於操作1

由於操作2的需要,vector[n]存下數

對於操作2的維護

查詢相鄰兩個元素的之間差值(絕對值)的最小值

先把所有答案存入乙個小頭堆裡

比如 a,c之間你要插入b

那麼,你就要刪除|c-a|,然後加入|a-b|,|c-b|

之後的堆頂就是ans啦

對於支援刪除的小頭堆,我只會fhqtreap代替

但我也不想寫, 因為太麻煩了

那麼,我們能不能用stl自帶的priority_queue

當然是可行的

維護兩個堆,x,y

ans存入x中,需要刪除的存入y中

每次更改的時候,改存的放入x,改刪的放入y

每當x.top()==y.top(),就一起刪掉,(注意!y.empty())

對於操作3的維護

查詢所有元素中最接近的兩個元素的差值(絕對值)

每次修改乙個數,對最優答案都不會有壞的影響(顯然)

那好的影響是啥

就是他和她的前驅,後繼的差(顯然)

注意前驅,後繼的存在性

最近老是不動腦子了(或者根本沒腦子?)

insert操作查詢前驅後繼的時候可以省去find操作

#include #include #include #include #include #include #define for(i,a,b) for(int i=a;i<=b;++i)

using namespace std;

const int maxn=5e5+7;

const int inf=0x3f3f3f3f;

inline int read()

int n,m,rt,ans2=inf,a[maxn],cnt;

struct node e[maxn*2];

vectorx[maxn];

priority_queue, greater> ans1,delet;

inline int abs(int a)

inline void pushup(int x)

inline void rotate(int x)

void splay(int x,int goal)

if(!goal) rt=x;

}void find(int a)

int build(int l,int r,int fa)

int main()

insert(b);

int x=e[qq(b)].val,y=e[hj(b)].val;

ans2=min(ans2,min(abs(x-b),abs(y-b)));

} else if(s[4]=='g') else if(s[4]=='s')

}return 0;

}

ZJOI2007 報表統計

不想描述了,心累。兩個操作分別用splay和線段樹來維護 全域性的差值最小直接用splay在插入的時候維護前驅後繼即可 相鄰最小差值我們可以這樣搞 首先 用線段樹維護相鄰的最小值 可以注意到插入元素的操作,如果是在乙個元素之後反覆插入,這些元素之間更新出來的最小值是不會發生改變的。只有元素與元素之間...

ZJOI2007 報表統計

在原數列第 i 個後面新增乙個新元素 k 如果原數列的第 i 個元素已經新增了若干元素,則新增在這些元素的最後。查詢相鄰兩個元素的差值的絕對值的最小值。查詢所有元素中一對元素的差值的絕對值的最小值。第乙個操作很好維護,若要在第 i 個元素後面插值,那麼實際需要插入的位置是 i s i 1 其中 s ...

ZJOI2007 報表統計

題解 一道不錯的模板題 對於第乙個詢問,只需維護乙個支援刪除的堆 方法1.再維護乙個堆,將刪除的數加入這個堆,每次取元素時判斷一下是否和另乙個堆相等 方法2.利用左偏樹可以刪除任意節點 太久不寫都忘了 當然也可以維護一顆平衡樹 對於第二個詢問,只需弄一顆平衡樹求它的前驅後繼就可以了 include ...