BZOJ1058 ZJOI2007 报表统计 线段树+平衡树
生活随笔
收集整理的這篇文章主要介紹了
BZOJ1058 ZJOI2007 报表统计 线段树+平衡树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:給定一個序列,維護:1、插入一個元素? 2、求相鄰兩個元素中,差值絕對值的最小值? 3、求序列排序后相鄰兩個元素中,差值絕對值的最小值
題解:
MIN_GAP:如果我們把數看成一組一組,每次插入數字都在一組的最后插入,那么答案只有可能在組內和組間兩個位置產生,定義l[i]為一組數中最左邊的數,r[i]為一組數中最右邊的數,新插入的數為x,那么用|x-l[i]|取min來更新組內的最小值,|x-r[i]|強制更新組間的值。因此我們需要能單點修改,區間查詢的數據結構,線段樹走起。
MIN_SORT_GAP:由于答案與數的位置無關,Splay走起。顯然與新插入的數x差值最小的數一定在插入過程走過的路經上(原因請自行腦補),開個ans維護答案即可。
這玩意比樹套樹啥的敲起來舒服多了
#include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <iostream> #include <algorithm> using namespace std;const int MAXN=500000+2; int N,Q,ans=INT_MAX,l[MAXN],r[MAXN]; char S[20+2];//Segment Tree begin typedef struct ST_NODE{int l,r,m;ST_NODE *lchild,*rchild;ST_NODE(){}ST_NODE(int _l,int _r):l(_l),r(_r),m(INT_MAX),lchild(0),rchild(0){} } *ST_TREE; ST_TREE ST_root;void ST_Pushup(ST_TREE &x){ x->m=min(x->lchild->m,x->rchild->m);}void ST_Build(ST_TREE &root,int l,int r){root=new ST_NODE(l,r);if(l==r) return;int m=(l+r)>>1;if(l<=m) ST_Build(root->lchild,l,m);if(m<r) ST_Build(root->rchild,m+1,r); }void ST_Insert(ST_TREE &x,int p,int a,bool t){if(x->l==x->r){if(t) x->m=a;else x->m=min(x->m,a);return;}int m=(x->l+x->r)>>1;if(p<=m) ST_Insert(x->lchild,p,a,t);else ST_Insert(x->rchild,p,a,t);ST_Pushup(x); } //Segment Tree end//Splay Tree begin typedef struct Splay_NODE{int v;Splay_NODE *child[2],*f;Splay_NODE(){}Splay_NODE(int _v,Splay_NODE *_f):v(_v),f(_f){} } *Splay_TREE; Splay_TREE Null,Splay_root;Splay_TREE NewNode(int v,Splay_TREE f){Splay_TREE x=new Splay_NODE(v,f);x->child[0]=x->child[1]=Null;return x; }void Splay_Init(){Null=NewNode(INT_MAX,0);Splay_root=NewNode(INT_MAX>>1,Null); }void Rotate(Splay_TREE &x,bool t){Splay_TREE y=x->f;y->child[!t]=x->child[t],x->child[t]->f=y,x->f=y->f;if(y->f->child[0]==y) y->f->child[0]=x;else y->f->child[1]=x;y->f=x,x->child[t]=y;if(y==Splay_root) Splay_root=x; }void Splay(Splay_TREE &x,Splay_TREE &y){while(x->f!=y)if(x->f->f==y)if(x->f->child[0]==x) Rotate(x,1);else Rotate(x,0);else if(x->f->f->child[0]==x->f)if(x->f->child[0]==x) Rotate(x->f,1),Rotate(x,1);else Rotate(x,0),Rotate(x,1);elseif(x->f->child[0]==x) Rotate(x,1),Rotate(x,0);else Rotate(x->f,0),Rotate(x,0); }void Splay_Insert(Splay_TREE &x,int a){Splay_TREE y=x,z;while(y!=Null){ans=min(ans,abs(a-y->v)),z=y;if(y->v>=a) y=y->child[0];else y=y->child[1];}if(z->v>=a) y=z->child[0]=NewNode(a,z);else y=z->child[1]=NewNode(a,z);Splay(y,Null); } //Splay Tree beginint main(){scanf("%d %d",&N,&Q);Splay_Init(),ST_Build(ST_root,1,2*N-1);for(int i=1;i<=N;i++){scanf("%d",l+i),r[i]=l[i];ST_Insert(ST_root,2*(i-1)+1,INT_MAX,0);if(i!=1) ST_Insert(ST_root,2*(i-1),abs(l[i-1]-l[i]),1);Splay_Insert(Splay_root,l[i]);}for(int i=1,x,y;i<=Q;i++){scanf("%s",S);if(strstr(S,"INSERT")){scanf("%d %d",&x,&y);ST_Insert(ST_root,2*(x-1)+1,abs(y-r[x]),0);if(x!=N) ST_Insert(ST_root,2*x,abs(y-l[x+1]),1);Splay_Insert(Splay_root,y);r[x]=y;}if(strstr(S,"MIN_GAP")) printf("%d\n",ST_root->m);if(strstr(S,"MIN_SORT_GAP")) printf("%d\n",ans);}return 0; } View Code?
轉載于:https://www.cnblogs.com/WDZRMPCBIT/p/6481635.html
總結
以上是生活随笔為你收集整理的BZOJ1058 ZJOI2007 报表统计 线段树+平衡树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Spring》(六)---- Bean
- 下一篇: 《怎样成为一个高手》观后感