BZOJ1058 ZJOI2007 報表統計

2022-03-29 17:44:54 字數 2782 閱讀 4326

bzoj1058: [zjoi2007]報表統計

小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寫了乙個程式,使得程式可以自動完成這些操作,但是他發現對於一些大的報表他的程式執行得很慢,你能幫助他改進程式麼?

第一行包含兩個整數n,m,分別表示原數列的長度以及操作的次數。

第二行為n個整數,為初始序列。

接下來的m行每行乙個操作,即「insert i k」,「min_gap」,「min_sort_gap」中的一種(無多餘空格或者空行)。

對於每乙個「min_gap」和「min_sort_gap」命令,輸出一行答案即可。

3 55 3 1

insert 2 9

min_sort_gap

insert 2 6

min_gap

min_sort_gap22

1n , m ≤500000 對於所有的資料,序列內的整數不超過5*10^8。

噁心到極致的卡常題。。。

維護兩個$treap$即可。 

為什麼不用$splay$?

因為這個題目$bzoj$用事實告訴我們:$splay$的常數是$treap$的許多倍。。。

第一顆$treap$:維護每個點,每次新加入乙個點時,找到前驅後繼,維護第$3$個操作的答案。 

第二顆$treap$:每次加入點時,維護相鄰兩個點之差的絕對值。

然後就沒了。

但是這題瘋狂卡常。。。

對於第$2$個操作,我們注意到,加入乙個點位置是$pos$時,$pos$與$pos-1$的差值不會消失,所以可以用乙個$ans$來維護$pos$與前驅的之間的值。

而$pos$與$pos+1$之間可能加入數字,所以用$treap$維護。不過,若差值小於$ans$,就不用再加入$treap$中了。

還有,對於第$3$個操作,在統計是只要發現有兩個數字相同,就做個標記,到後面詢問時直接輸出$0$即可。

以上所說的差值都要加絕對值。

然後就可以跑了。。。

附**:

#include#include#include#define maxn 500010

#define max 999999999

using namespace std;

int n,m,minn=max;

int head[maxn],last[maxn];

bool flag;

struct node

};node* one;node* two;

inline int read()

while(c>='0'&&c<='9')

return date*w;

}inline void write(int x)

if(x>9)write(x/10);

putchar(x%10+'0');

}inline long long abs(const long long x)

inline long long min(const long long x,const long long y)

void turn(node* &u,int f)

void insert(node* &u,int x)

else if(u->v==x)

int y=u->vson[y],x);

if(u->son[y]->w>u->w)turn(u,y^1);

else maintain(u);

}void remove(node* &u,int x)

else

}else

} if(u!=null)maintain(u);

} else

}int kth(node* u,int k)

void front(node* u,int k,int &ans)

else if(u->v>=k)

if(u->son[0]!=null)front(u->son[0],k,ans);

}void next(node* u,int k,int &ans)

else if(u->v<=k)

if(u->son[1]!=null)next(u->son[1],k,ans);

}void update(int v)

void work()

last[x]=y;

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

else }}

void init()

flag=false;

for(int i=1;i}int main()

bzoj1058 ZJOI2007 報表統計

小q的媽媽是乙個出納,經常需要做一些統計報表的工作。今天是媽媽的生日,小q希望可以幫媽媽分擔一些工作,作為她的生日禮物之一。經過仔細觀察,小q發現統計一張報表實際上是維護乙個可能為負數的整數數列,並且進行一些查詢操作。在最開始的時候,有乙個長度為n的整數序列,並且有以下三種操作 insert i k...

bzoj1058 ZJOI2007 報表統計

傳送門 題解 這個insert操作好py啊是不是用set就能搞搞啊。什麼?你跟我講t了?讀入優化?還是t?卡了卡常,發現乙個東西用priority queue就夠了。然後12s過了。include include include include include include include usi...

bzoj1058 ZJOI2007 報表統計

題目大意 給定乙個序列,有多次詢問和修改,將新元素插在原數列位置的後面,詢問相鄰元素差值最小,和數列中兩元素最小的差。stl解法 用乙個set去維護相鄰兩個數差的最小值,用乙個堆去維護所有序列中最小的差 includeusing namespace std define inf 1000000000...