生活随笔
收集整理的這篇文章主要介紹了
bzoj 1058: [ZJOI2007]报表统计
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
小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寫了一個程序,使
得程序可以自動完成這些操作,但是他發現對于一些大的報表他的程序運行得很慢,你能幫助他改進程序么?
solution
正解:堆+平衡樹
又墮落了QwQ,說好的平衡樹呢?
對于第一個操作,我們鏈表維護一下即可
對于第二個詢問,我們維護一個堆,我們每加入一個元素就把與前后差值加入堆中,堆中記錄后繼,便于刪除.
對于第三個詢問,答案單調不升,直接平衡樹維護全局變量,插入時取min即可
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
#include <set>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=1000005,inf=2e9;
int n,m,nxt[N],cnt=0,pre[N],val[N],last[N],b[N];
char S[41];
struct node{int x,y,val;bool operator <(const node &pr)const{return val>pr.val;}
};
priority_queue<node>q;
multiset<int>G;
multiset<int>::iter it;
void work()
{int x,y,z,ans=inf;node k;scanf("%d%d",&n,&m);cnt=n;for(int i=1;i<=n;i++){scanf("%d",&val[i]);b[i]=val[i];last[i]=i;pre[i]=i-1;nxt[i]=i+1;if(i!=1)q.push((node){i-1,i,abs(val[i]-val[i-1])});G.insert(val[i]);}sort(b+1,b+n+1);for(int i=2;i<=n;i++)ans=min(ans,b[i]-b[i-1]);G.insert(-inf);G.insert(inf);while(m--){scanf("%s",S);if(S[0]=='I'){scanf("%d%d",&x,&z);y=last[x];cnt++;val[cnt]=z;if(x<n)pre[x+1]=cnt,nxt[cnt]=x+1;last[x]=cnt;nxt[y]=cnt;pre[cnt]=y;q.push((node){y,cnt,abs(val[y]-z)});if(x<n)q.push((node){cnt,x+1,abs(val[x+1]-z)});it=G.lower_bound(z);if(*it!=-inf){ans=min(ans,abs(*it-z));--it;if(*it!=-inf)ans=min(ans,abs(*it-z));}it=G.upper_bound(z);if(*it!=inf)ans=min(ans,abs(*it-z));G.insert(z);}else if(S[4]=='G'){while(!q.empty()){k=q.top();if(nxt[k.x]!=k.y)q.pop();else {printf("%d\n",k.val);break;}}}else printf("%d\n",ans);}
}int main()
{freopen("pp.in","r",stdin);freopen("pp.out","w",stdout);work();return 0;
}
轉載于:https://www.cnblogs.com/Yuzao/p/8040437.html
總結
以上是生活随笔為你收集整理的bzoj 1058: [ZJOI2007]报表统计的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。