這裡的初始化就不講了,看完操作講解就應該明白了,再不行就去看**
對於操作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 ...