首页 > 其他 > 详细

[CQOI 2014] 排序机械臂

时间:2014-04-08 05:01:44      阅读:582      评论:0      收藏:0      [点我收藏+]

bubuko.com,布布扣

看完此题数据范围n<=100000,就知道与模拟无缘了(不知道是脑残还是怎样,第一次做的时候由于只剩下半个小时,于是匆匆写了个模拟,然后光荣的爆0了,原因很简单,我把题目看错了T_T)

就是这句话:如果有高度相同的物品,必须保证他们排序后与初始的相对位置关系相同。

被样例2骗了,SB的写了一个错误的DP,然后由于splay太长时间没写,所以……

对于这个限制条件,我给每个点加上了时间标记dnf(这当然不是tarjan……随手写写而已)

然后加上三个与DP相关的域:mi,ti,pos,分别表示当前区间可以取到的最小值、该最小值所对应的时间戳,要达到该最小值该怎么走(pos=0时为本身,pos=1时向左走,pos=2时向右走),然后DP方程就可以随便写了,另外涉及反转区间加上rev域,这个真是做烂了,没什么好说的。

好不容易把splay写完了,结果TLE(我开始质疑这台电脑了),无奈之下,将初始的链建成一棵二叉树,还是TLE,然后只好到bzoj上提交,两份代码都AC了,相差几十毫秒(坑爹啊!)

这一次偷懒没写自顶向下的splay,写的是自底向上的,感觉WJMZBMR的思路太神奇了,splay那么短(十分感动……)

其他就没有什么好说了,上代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <map>
#define setc(x,s,d) (p[c[x][d]=s]=x,update(x))
#define root(x) (!p[x])
#define ch(x) (c[p[x]][1]==x)
#define _rev(x) (rev[x]^=1)
#define MaxN 100010
using namespace std;
const int INF=~0U>>2;
int n,t,x,ans;
int a[MaxN],c[MaxN][2],p[MaxN],sz[MaxN];
int pos[MaxN],mi[MaxN],dfn[MaxN],ti[MaxN];
bool rev[MaxN];
map<int,int> m;
map<int,int>::iterator iter;
inline void push(const int &x)
{
	if(!x) return;
	if(rev[x])
	{
		swap(c[x][0],c[x][1]);
		pos[x]=3-pos[x];
		pos[x]%=3;
		if(c[x][0]) _rev(c[x][0]);
		if(c[x][1]) _rev(c[x][1]);
		rev[x]=0;
	}
}
inline void update(const int &x)
{
	if(!x) return;
	sz[x]=sz[c[x][0]]+1+sz[c[x][1]];
	mi[x]=a[x],pos[x]=0,ti[x]=dfn[x];
	for(int i=0;i<2;i++)
		if(mi[c[x][i]]<mi[x])
			mi[x]=mi[c[x][i]],
			pos[x]=i+1,
			ti[x]=ti[c[x][i]];
		else if(mi[c[x][i]]==mi[x])
			if(ti[c[x][i]]<ti[x])
				pos[x]=i+1,
				ti[x]=ti[c[x][i]];
}
inline void rorate(const int &x)
{
	int f=p[x];
	bool d=ch(x);
	setc(f,c[x][!d],d);
	if(root(f)) p[x]=p[f];
	else setc(p[f],x,ch(f));
	setc(x,f,!d);
}
inline int find(int &t)
{
	int ans=0;
	push(t);
	while(pos[t])
	{
		if(pos[t]-1) ans+=sz[c[t][0]]+1;
		t=c[t][pos[t]-1];
		push(t);
	}
	return ans+sz[c[t][0]];
}
inline void splay(int rt,int x)
{
	while(p[x]!=rt)
		if(p[p[x]]==rt)
			rorate(x);
		else if(ch(x)==ch(p[x]))
			rorate(p[x]),rorate(x);
		else if(p[p[x]]!=rt)
			rorate(x),rorate(x);
		else rorate(x);
}
inline int side(int x)
{
	push(x);
	while(c[x][0])
		x=c[x][0],
		push(x);
	return x;
}
inline void work()
{
	for(int i=1;i<n;i++)
	{
		x=t;
		ans=find(x);
		printf("%d ",ans+i);
		splay(0,x);
		if(c[x][1])
			splay(x,side(c[x][1])),
			t=c[x][1],
			setc(t,c[x][0],0),
			_rev(c[x][0]);
		else
			t=c[x][0],
			_rev(t);
		p[t]=0;
	}
	printf("%d\n",n);
}

int build(int l,int r)
{
	if(l>r) return 0;
	int m=(l+r)>>1;
	if(l!=r)
		p[c[m][0]=build(l,m-1)]=m,
		p[c[m][1]=build(m+1,r)]=m;
	update(m);
	return m;
}

inline void init()
{
	mi[0]=dfn[0]=ti[0]=INF;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		iter=m.find(a[i]);
		if(iter==m.end())
			m.insert(make_pair(a[i],0));
		else dfn[i]=++(iter->second);
//		setc(i,i-1,0);
	}
	t=build(1,n);
//	t=n;
}
int main()
{
//	freopen("sort.in","r",stdin);
//	freopen("sort.out","w",stdout);
	init();
	work();
	return 0;
}

[CQOI 2014] 排序机械臂,布布扣,bubuko.com

[CQOI 2014] 排序机械臂

原文:http://blog.csdn.net/doveccl/article/details/23128321

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!