[BZOJ]4864: [BeiJing 2017 Wc]神秘物质
题解: 操作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 MBSubmit: 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
5 8 10 2
max 1 3
min 1 3
max 2 4
Sample Output
5 2 8