【BZOJ4864】【BJWC2017】神祕物質 - Splay

題意:

Description

21ZZ 年,冬。小誠退休之後, 不知爲什麼從新燃起了對物理學的興趣。 他從研究所借了些實驗儀器,成天研究各類微觀粒子。這一天, 小誠剛從研究所獲得了一塊奇異的隕石樣本, 便火燒眉毛地開始觀測。 在精密儀器的視野下,構成隕石的每一個原子都無比清晰。 小誠發現, 這些原子排成若干列, 每一列的結構具備高度類似性。因而,他決定對單獨一列原子進行測量和測試。被選中的這列共有 N 個順序排列的原子。 最初, 第 i 個原子具備能量 Ei。 隨着時間推移和人爲測試, 這列原子在觀測上會產生兩種變化:node

merge x e 當前第 x 個原子和第 x+1 個原子合併,獲得能量爲 e 的新原子;ios

insert x e 在當前第 x 個原子和第 x+1 個原子之間插入一個能量爲 e 的新原子。測試

對於一列原子,小誠關心的是相鄰一段中能量最大和能量最小的兩個原子的能量差值,ui

稱爲區間極差。 所以, 除了觀測變化外,小誠還要常常統計這列原子的兩類數據:spa

max x y 當前第 x 到第 y 個原子之間的任意子區間中區間極差的最大值;code

min x y 當前第 x 到第 y 個原子之間的任意子區間中區間極差的最小值。blog

其中, 子區間指的是長度至少是 2 的子區間。事件

小誠堅信這項研究能夠得到諾貝爾物理學獎。爲了讓小誠早日告終心願,你可否幫助他實現上述的觀測和測量呢?ip

Input

第一行, 兩個整數 N, M, 分別表示最初的原子數目和事件總數。
第二行, N 個整數 E1, E2, …, EN, 由空格隔開。依次表示每一個原子的能量。
接下來 M 行, 每行爲一個字符串和兩個整數, 描述一次事件,格式見題目描述。
N<=100,000,M<=100,000 1 ≤ e, Ei ≤ 109。
設 N’ 爲當前時刻原子數目。 對於 merge 類事件, 1 ≤ x ≤ N’-1;
對於 insert 類事件, 1 ≤ x ≤ N’;
對於 max 和 min 類事件, 1 ≤ x < y ≤ N’。
任什麼時候刻,保證 N’ ≥ 2。

Output

輸出若干行, 按順序依次表示每次 max 和 min 類事件的測量結果。字符串

題解:

看到merge和insert操做確定是splay維護啦……

考慮如何處理詢問,極差最大值確定是區間最大值減最小值,這個不用說;

極差最小值呢?

結論是極差最小值必定是兩個相鄰的數之差;

考慮三個數,確定選中間的數和與其差較小的另外一個數極差最小,三個數都選不會優於這個選擇,相似概括便可;

那麼splay維護子樹最大/最小值,前驅後繼和子樹內最小極差,pushup的時候搞搞便可。

代碼:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #define inf 1000000007
 8 #define eps 1e-9
 9 using namespace std;  10 typedef long long ll;  11 typedef double db;  12 struct node{  13     int son[2],fa,v,l,r,siz,mi,mx,mm;  14 }t[200001];  15 int n,m,x,y,rt,cnt,num[200001];  16 char op[10];  17 bool Son(int u){  18     return t[t[u].fa].son[1]==u;  19 }  20 void pushup(int u){  21     t[u].l=t[u].son[0]?t[t[u].son[0]].l:u;  22     t[u].r=t[u].son[1]?t[t[u].son[1]].r:u;  23     t[u].siz=t[t[u].son[0]].siz+t[t[u].son[1]].siz+1;  24     t[u].mx=max(t[u].v,max(t[t[u].son[0]].mx,t[t[u].son[1]].mx));  25     t[u].mi=min(t[u].v,min(t[t[u].son[0]].mi,t[t[u].son[1]].mi));  26     t[u].mm=min(min(t[t[u].son[0]].mm,t[t[u].son[1]].mm),min(t[u].son[0]?abs(t[u].v-t[t[t[u].son[0]].r].v):inf,t[u].son[1]?abs(t[u].v-t[t[t[u].son[1]].l].v):inf));  27 }  28 int build(int l,int r,int ff){  29     int mid=(l+r)/2;  30     t[mid].fa=ff;  31     if(l<mid)t[mid].son[0]=build(l,mid-1,mid);  32     if(mid<r)t[mid].son[1]=build(mid+1,r,mid);  33  pushup(mid);  34     return mid;  35 }  36 void rotate(int u){  37     int f=t[u].fa,ff=t[f].fa,ch=Son(u),cf=Son(f);  38     t[f].son[ch]=t[u].son[ch^1];  39     t[t[f].son[ch]].fa=f;  40     t[ff].son[cf]=u;  41     t[u].son[ch^1]=f;  42     t[u].fa=ff;  43     t[f].fa=u;  44  pushup(f);  45  pushup(u);  46 }  47 void splay(int u,int to){  48     for(;t[u].fa!=to;rotate(u)){  49         int f=t[u].fa;  50         if(t[f].fa!=to)rotate(Son(u)^Son(f)?u:f);  51  }  52     if(!to)rt=u;  53 }  54 int findx(int u,int k){  55     int nw=u;  56     for(;;){  57         if(t[t[nw].son[0]].siz+1==k)return nw;  58         if(k<=t[t[nw].son[0]].siz){  59             nw=t[nw].son[0];  60         }else{  61             k-=t[t[nw].son[0]].siz+1;  62             nw=t[nw].son[1];  63  }  64  }  65 }  66 int split(int x,int y){  67     int l=findx(rt,x-1),r=findx(rt,y+1);  68     //printf("%d %d\n",l,r);
 69     splay(l,0);  70  splay(r,rt);  71     return t[t[rt].son[1]].son[0];  72 }  73 void merge(int x,int y){  74     int u=split(x+1,x+2);  75     t[u].v=y;  76     t[u].son[0]=t[u].son[1]=0;  77  pushup(u);  78     pushup(t[rt].son[1]);  79  pushup(rt);  80 }  81 void ins(int x,int y){  82     int u=split(x+2,x+1);  83     t[t[rt].son[1]].son[0]=++cnt;  84     t[cnt].fa=t[rt].son[1];  85     t[cnt].v=y;  86  pushup(cnt);  87     pushup(t[rt].son[1]);  88  pushup(rt);  89 }  90 int getmx(int x,int y){  91     int u=split(x+1,y+1);  92     return t[u].mx-t[u].mi;  93 }  94 int getmi(int x,int y){  95     int u=split(x+1,y+1);  96     return t[u].mm;  97 }  98 int main(){  99     scanf("%d%d",&n,&m); 100     cnt=n+2; 101     for(int i=1;i<=n;i++){ 102         scanf("%d",&t[i+1].v); 103  } 104     t[0].mx=0; 105     t[0].mi=t[0].mm=inf; 106     cnt=n+2; 107     rt=build(1,n+2,0); 108     for(int i=1;i<=m;i++){ 109         scanf("%s%d%d",op,&x,&y); 110         if(op[1]=='e'){ 111  merge(x,y); 112         }else if(op[1]=='n'){ 113  ins(x,y); 114         }else if(op[1]=='a'){ 115             printf("%d\n",getmx(x,y)); 116         }else{ 117             printf("%d\n",getmi(x,y)); 118  } 119  } 120     return 0; 121 }
相關文章
相關標籤/搜索