bzoj4864: [BeiJing 2017 Wc]神秘物质


4864: [BeiJing 2017 Wc]神秘物质

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 99  Solved: 56
[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 的子区间。
小诚坚信这项研究可以获得诺贝尔物理学奖。为了让小诚早日了结心愿,你能否帮助他实现上述的观测和测量呢?

哇啊啊啊啊啊啊

这道题对我这个蒟蒻来说好复杂!!!

没有看别人的代码

全是自己yy的(有些是问师兄的QAQ)

写了接近三个小时,调来调去

pushup函数写错了也调了好久

不过写完了好激动啊啊啊啊

有点懒,具体细节就不讲啦

其实就是splay

然后要维护两点之前差的绝对值的最小值

其他的都没什么了

代码力不够,好多细节都处理了很久

不说了不说了

激动着呢

还排了status 13(虽然只有56人AC)

#include<cstdio>
#include<cmath>
#include<iostream>
const int N=2*1e5+100;
struct node
{
	int c[2],fa,size,v,max,min,cha,chamin;
}tr[N];
int root,n,cd;
int read()
{
	int ans=0;char t=getchar();
	while(t<'0'||t>'9')		t=getchar();
	while(t>='0'&&t<='9')	ans=ans*10+t-'0',t=getchar();
	return ans;
}
void pushup(int k)
{
	int l=tr[k].c[0],r=tr[k].c[1];
	tr[k].size=tr[l].size+tr[r].size+1;
	if(k==1||k==n+2||k==2)	
	{
		if(k!=2)	tr[k].max=0,tr[k].min=1e8;
		else tr[k].max=tr[k].min=tr[k].v,tr[k].chamin=tr[k].cha;
		tr[k].chamin=1e8;
	}
	else tr[k].max=tr[k].min=tr[k].v,tr[k].chamin=tr[k].cha;
	if(l)	tr[k].max=std::max(tr[l].max,tr[k].max),tr[k].min=std::min(tr[k].min,tr[l].min),tr[k].chamin=std::min(tr[k].chamin,tr[l].chamin);
	if(r)	tr[k].max=std::max(tr[r].max,tr[k].max),tr[k].min=std::min(tr[k].min,tr[r].min),tr[k].chamin=std::min(tr[k].chamin,tr[r].chamin);
}
void build(int l,int r,int fa)
{
	if(l>r)	return ;
	if(l==r)
	{
		tr[l].size=1;tr[l].fa=fa;
		if(l<fa)	tr[fa].c[0]=l;
		else 		tr[fa].c[1]=l;
		if(l==1||l==n+2)	tr[l].min=1e8,tr[l].chamin=1e8;
		else tr[l].max=tr[l].min=tr[l].v,tr[l].chamin=tr[l].cha;
		if(l==2)	tr[l].chamin=1e8;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid-1,mid);build(mid+1,r,mid);
	tr[mid].fa=fa;pushup(mid);
	if(mid<fa)	tr[fa].c[0]=mid;
	else 		tr[fa].c[1]=mid;
}
void rotate(int x,int &k)
{
	int y=tr[x].fa,z=tr[y].fa,l,r;
	if(tr[y].c[0]==x)	l=0;else l=1;r=l^1;
	if(y==k)	k=x;
	else 
	{
		if(tr[z].c[0]==y)		tr[z].c[0]=x;
		else 					tr[z].c[1]=x;
	}	
	tr[x].fa=z;tr[y].fa=x;	
	tr[tr[x].c[r]].fa=y;		tr[y].c[l]=tr[x].c[r]; 		tr[x].c[r]=y;
	pushup(y),pushup(x);
}
void splay(int x,int &k)
{
	int y,z;
	while(x!=k)
	{
		y=tr[x].fa,z=tr[y].fa;
		if(y!=k)
		{
			if((tr[y].c[0]==x)^(tr[z].c[0]==y))	rotate(x,k);
			else rotate(y,k);
		}
		rotate(x,k);
	}
}
int find (int k,int rank)
{
	int l=tr[k].c[0];
	if(rank==tr[l].size+1)	return k;
	if(rank<tr[l].size+1)	return find(l,rank);
	return find(tr[k].c[1],rank-tr[l].size-1);		
}
void merge(int u,int k)
{
	int x=find(root,u);		splay(x,root);
	int y=find(root,u+3);	splay(y,tr[root].c[1]);
	int q=tr[tr[root].c[1]].c[0];
	tr[q].v=tr[q].min=tr[q].max=k;tr[q].size=1;
	tr[q].c[0]=tr[q].c[1]=0;
	tr[q].cha=tr[q].chamin=fabs(k-tr[root].v);
	tr[tr[root].c[1]].cha=fabs(k-tr[tr[root].c[1]].v);
	pushup(tr[root].c[1]);pushup(root);
}
void insert(int u,int k)
{
	int x=find(root,u+1);	splay(x,root);
	int y=find(root,u+2);	splay(y,tr[root].c[1]);
	int q=tr[root].c[1];
	tr[q].c[0]=++cd;tr[cd].fa=q;
	q=tr[q].c[0];
	tr[q].v=tr[q].max=tr[q].min=k;tr[q].size=1;
	tr[q].cha=tr[q].chamin=fabs(k-tr[root].v);tr[tr[root].c[1]].cha=fabs(k-tr[tr[root].c[1]].v);
	pushup(tr[root].c[1]);pushup(root);
}
void max(int l,int r)
{
	int x=find(root,l); 	splay(x,root);
    int y=find(root,r+2); 	splay(y,tr[root].c[1]);
	int q=tr[y].c[0];
	printf("%d\n",tr[q].max-tr[q].min);
}
void min(int l,int r)
{
	int x=find(root,l+1);	splay(x,root);
	int y=find(root,r+2);splay(y,tr[root].c[1]);
	int q=tr[tr[root].c[1]].c[0];
	printf("%d\n",tr[q].chamin);
}
int main()
{
	int m,l;
	scanf("%d %d",&n,&m);scanf("%d",&tr[2].v);l=tr[2].v;
	for(int i=3;i<=n+1;i++)		
	{
		tr[i].v=read();
		tr[i].cha=fabs(tr[i].v-l);
		l=tr[i].v;
	}
	build(1,n+2,N-10);cd=n+2;
	root=tr[N-10].c[0];
	char a[10];int u,v;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",a);u=read(),v=read();
		if(a[1]=='e')	merge(u,v);
		else if(a[1]=='n')	insert(u,v);
		else if(a[1]=='a')	max(u,v);
		else min(u,v);
	}
	return 0;
}




posted @ 2017-05-31 21:55  Brian551  阅读(154)  评论(0编辑  收藏  举报