1. 程式人生 > >[BZOJ]4864: [BeiJing 2017 Wc]神秘物質

[BZOJ]4864: [BeiJing 2017 Wc]神秘物質

nbsp 接下來 urn 一段 page 結點 行為 turn else if

題解: 操作1 分解為刪除一個元素和修改一個元素的權值

   操作2:插入一個元素

   操作3:查詢區間裏面子區間的極差最大值 等價於直接求區間最大值減去區間最小值

   操作4:查詢區間子區間裏面極差最小值 首先明確 極差的最小值只會是相鄰元素產生 證明如下(假如 相鄰元素x,y,z 若極差最小值來源於z-x 那麽必然 滿足x<y<z 但顯然 在這種情況下 z-y優於z-x 所以推出極差最小值只會是相鄰元素產生)

推到這裏就是splay裸題了

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
const int inf=2e9;
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}

int pre[MAXN],ch[MAXN][2],key[MAXN],lk[MAXN],rk[MAXN],minn[MAXN],maxx[MAXN],Lmin[MAXN],sz[MAXN];
int cnt,rt;
void Treavel(int x)
{
    if(x)
    {
        Treavel(ch[x][0]);
        printf("結點%2d:左兒子 %2d 右兒子 %2d 父結點 %2d size=%2d key=%2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],key[x]);
        Treavel(ch[x][1]);
    }
}
void debug(int rp)
{
    printf("root:%d\n",rp);
    Treavel(rp);
}
void newnode(int &x,int t,int fa){
    x=++cnt;
    pre[x]=fa;ch[x][0]=ch[x][1]=0;key[x]=lk[x]=rk[x]=t;
    minn[x]=maxx[x]=t;Lmin[x]=inf;sz[x]=1;
}

void up(int x){
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    minn[x]=maxx[x]=key[x];Lmin[x]=inf;
    lk[x]=rk[x]=key[x];
    if(ch[x][0])lk[x]=lk[ch[x][0]],minn[x]=min(minn[x],minn[ch[x][0]]),maxx[x]=max(maxx[x],maxx[ch[x][0]]),Lmin[x]=min(min(Lmin[x],abs(rk[ch[x][0]]-key[x])),Lmin[ch[x][0]]);
    if(ch[x][1])rk[x]=rk[ch[x][1]],minn[x]=min(minn[x],minn[ch[x][1]]),maxx[x]=max(maxx[x],maxx[ch[x][1]]),Lmin[x]=min(min(Lmin[x],abs(lk[ch[x][1]]-key[x])),Lmin[ch[x][1]]);
}

void rotate(int x,int kind){
    int y=pre[x];
    pre[ch[x][kind]]=y;ch[y][!kind]=ch[x][kind];
    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
    up(y);
}

void splay(int x,int goal){
    while(pre[x]!=goal){
	if(pre[pre[x]]==goal)rotate(x,ch[pre[x]][0]==x);
	else{
	    int y=pre[x];int kind=ch[pre[y]][0]==y;
	    if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
	    else rotate(y,kind),rotate(x,kind);
	}
    }
    if(goal==0)rt=x;
    up(x);
}

int find1(int x,int k){
    if(k==sz[ch[x][0]]+1)return x;
    else if(k<=sz[ch[x][0]])return find1(ch[x][0],k);
    else return find1(ch[x][1],k-sz[ch[x][0]]-1);
}

void merge(int x,int e){
    splay(find1(rt,x+1),0);
    splay(find1(rt,x+3),rt);
    ch[ch[rt][1]][0]=0;key[rt]=e;
    up(ch[rt][1]);up(rt);
}

void insert(int x,int e){
    splay(find1(rt,x+1),0);
    splay(find1(rt,x+2),rt);
    newnode(ch[ch[rt][1]][0],e,ch[rt][1]);
    up(ch[rt][1]);up(rt);
}

void Max(int x,int y){
    splay(find1(rt,x),0);
    splay(find1(rt,y+2),rt);
    int t=ch[ch[rt][1]][0];
    printf("%d\n",maxx[t]-minn[t]);
}

void Min(int x,int y){
    splay(find1(rt,x),0);
    splay(find1(rt,y+2),rt);
    int t=ch[ch[rt][1]][0];
    printf("%d\n",Lmin[t]);
}

int a[MAXN],n,m;

void built(int &x,int l,int r,int y){
    if(l>r)return ;
    int mid=(l+r)>>1;
    newnode(x,a[mid],y);
    built(ch[x][0],l,mid-1,x);
    built(ch[x][1],mid+1,r,x);
    up(x);
}

void inte(){
    newnode(rt,0,0);
    newnode(ch[rt][1],0,rt);
    built(ch[ch[rt][1]][0],1,n,ch[rt][1]);
    up(ch[rt][1]);up(rt);
}

int main(){
    n=read();m=read();cnt=0;
    inc(i,1,n)a[i]=read();
    inte();int x,y;
    char str[11];
    while(m--){
	scanf("%s",str);x=read();y=read();
	if(str[1]==‘e‘)merge(x,y);
	else if(str[0]==‘i‘)insert(x,y);
	else if(str[1]==‘a‘)Max(x,y);
	else Min(x,y);
    }
    return 0;
}

  

4864: [BeiJing 2017 Wc]神秘物質

Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 453 Solved: 205
[Submit][Status][Discuss]

Description

21ZZ 年,冬。 小誠退休以後, 不知為何重新燃起了對物理學的興趣。 他從研究所借了些實驗儀器,整天研究各種微觀粒子。這 一天, 小誠剛從研究所得到了一塊奇異的隕石樣本, 便迫不及待地開始觀測。 在精密儀器的視野下,構成隕石 的每個原子都無比清晰。 小誠發現, 這些原子排成若幹列, 每一列的結構具有高度相似性。於是,他決定對單 獨一列原子進行測量和測試。被選中的這列共有 N 個順序排列的原子。 最初, 第 i 個原子具有能量 Ei。 隨著 時間推移和人為測試, 這列原子在觀測上會產生兩種變化: merge x e 當前第 x 個原子和第 x+1 個原子合並,得到能量為 e 的新原子; insert x e 在當前第 x 個原子和第 x+1 個原子之間插入一個能量為 e 的新原子。 對於一列原子,小誠關心的是相鄰一段中能量最大和能量最小的兩個原子的能量差值, 稱為區間極差。 因此, 除了觀測變化外,小誠還要經常統計這列原子的兩類數據: max x y 當前第 x 到第 y 個原子之間的任意子區間中區間極差的最大值; min x y 當前第 x 到第 y 個原子之間的任意子區間中區間極差的最小值。 其中, 子區間指的是長度至少是 2 的子區間。 小誠堅信這項研究可以獲得諾貝爾物理學獎。為了讓小誠早日了結心願,你能否幫助他實現上述的觀測和測量呢?

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 類事件的測量結果。

Sample Input

4 3
5 8 10 2
max 1 3
min 1 3
max 2 4

Sample Output

5 2 8

[BZOJ]4864: [BeiJing 2017 Wc]神秘物質