洛谷P1110\BZOJ1058 [ZJOI2007]報表統計

       \ \ \ \ \ \ \,第一次看見這個題:想了一會,woc,三顆平衡樹,好麻煩呀,先放一放。

       \ \ \ \ \ \ \,第二次看見這個題:想了一會,woc,平衡樹加線段樹,好麻煩呀,先放一放。

       \ \ \ \ \ \ \,第三次看見這個題:想了一會,woc,一棵權值平衡樹加一棵位置平衡樹,好麻煩呀,先放一放。

       \ \ \ \ \ \ \,第四次看見這個題:想了一會,woc,一棵平衡樹加堆,好麻煩呀……誒等等,好像可以就開兩個差不多的平衡樹就行了……


       \ \ \ \ \ \ \,寫的時候腦袋有點懵,不過還是肝好了呢。

       \ \ \ \ \ \ \,當他插入的時候,顯然可以發現,就是在堆裏面刪除元素:abs(head[id+1]tail[id])abs(head[id+1]-tail[id]);然後插入兩個新元素:abs(head[id+1]new)abs(head[id+1]-new)abs(newtail[id])abs(new-tail[id])。然後新的 tail[id]tail[id] 再附上 newnew。每次詢問 MIN_GAPMIN\_GAP 就是詢問堆裏面的最小值了。

       \ \ \ \ \ \ \,支持刪除,插入,查詢權值最小,顯然可以用平衡樹去搞。

       \ \ \ \ \ \ \,對於第二種詢問,單獨插入一個元素,我們需要在集合裏面查找他的前驅和後繼,便可以計算最小的差值,顯然這個詢問的答案是單調的,所以我們開全局變量去記錄。

       \ \ \ \ \ \ \,支持插入,查前驅,查後繼,顯然可以又用平衡樹去搞。

       \ \ \ \ \ \ \,這裏我用了我喜歡的FhqTreapFhq_Treap,然後前驅後繼是直接查的,其實可以通過pushuppushup上傳最大最小值,但是不知道爲什麼會慢一點,然後卡了會兒常,代碼有點醜:

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<map>
#include<set>
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
  int x=0,f=1;char ch;ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
  if(f)return x;else return -x;
}
const int N=1000010;
int ans=inf;
inline int Abs(const int &a){if(a<0)return -a;return a;}
inline int min(const int &a,const int &b){if(a<b)return a;return b;}
inline int max(const int &a,const int &b){if(a>b)return a;return b;}
struct fhq_treap_val{
  #define lson ls[rt]
  #define rson rs[rt]
  int val[N],size[N],key[N];
  int ls[N],rs[N];
  int root,cnt;
  void pushup(int rt){size[rt]=size[lson]+size[rson]+1;}
  int merge(int a,int b){
    if(!a||!b)return a|b;
    if(key[a]<key[b]){rs[a]=merge(rs[a],b);pushup(a);return a;}
    else {ls[b]=merge(a,ls[b]);pushup(b);return b;}
  }
  void split(int rt,int x,int &a,int &b){
    if(!rt){a=b=0;return;}
    if(val[rt]<=x){a=rt;split(rson,x,rson,b);}
    else{b=rt;split(lson,x,a,lson);}
    pushup(rt);
  }
  int Max(int rt){while(rson)rt=rson;return val[rt];}
  int Min(int rt){while(lson)rt=lson;return val[rt];}
  int newnode(int x){
    int rt=++cnt;
    val[rt]=x;
    size[rt]=1;key[rt]=rand();
    lson=rson=0;
    return rt;
  }
  void Insert(int x){
    int a,b;
    split(root,x,a,b);
    int rt=newnode(x);
    root=merge(merge(a,rt),b);
  }
  void Insert_2(int x){
    int a,b;
    split(root,x,a,b);
    if(size[a])ans=min(ans,abs(x-Max(a)));
    if(size[b])ans=min(ans,abs(Min(b)-x));
    int rt=newnode(x);
    root=merge(merge(a,rt),b);
  }
  void Delete(int x){
    int a,b,c;
    split(root,x,a,c);
    split(a,x-1,a,b);
    b=merge(ls[b],rs[b]);
    root=merge(merge(a,b),c);
  }
}T1,T2;
int n,m,a[N],b[N],id,g;
char op[20];
int main()
{
  srand(time(NULL));
  n=read();m=read();
  for(int i=1;i<=n;i++)a[i]=b[i]=read();
  for(int i=1;i<n;i++)T1.Insert(Abs(a[i+1]-a[i]));
  for(int i=1;i<=n;i++)T2.Insert_2(a[i]);
  while(m--){
    scanf("%s",op);
    if(op[0]=='I'){
      id=read();g=read();
      T2.Insert_2(g);
      if(id!=n){
        T1.Delete(Abs(a[id+1]-b[id]));
        T1.Insert(Abs(a[id+1]-g));
      }
      T1.Insert(Abs(b[id]-g));
      b[id]=g;
    }
    else if(op[4]=='G')printf("%d\n",T1.Min(T1.root));
    else printf("%d\n",ans);
  }
  return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章