bzoj1552robotic sort splay

1552: [Cerc2007]robotic sort

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 1235   Solved: 471
[ Submit][ Status][ Discuss]

Description

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6

HINT

Source


用splay维护值最小的结点编号和它的值,然后就很暴力了,每次把区间整出来,然后先找到后输出,再强行整出要翻转的区间,暴力打标记就可以了
关于相同的东东,直接排个序离散化就可以了。。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
#define maxn 110000
#define inf 0x7fffffff
#define ls t[p].ch[0]
#define rs t[p].ch[1]
#define pa t[p].f
using namespace std;
int read() {
	char ch = getchar(); int x = 0, f = 1;
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = x * 10 - '0' + ch; ch = getchar();}
	return x * f;
}

struct node {
	int ch[2], f; bool rev;
	int v, size, mn, pos;
	node() {}
	node(int val, int fa, int po) {
		v = mn = val; f = fa; pos = po;
		size = 1; ch[0] = ch[1] = rev = 0;
	}
}t[maxn]; int root, sz, n;
int wh(int p) {return t[pa].ch[1] == p;}

struct data {
	int v, id;
	bool operator<(const data& a) const {
		return v == a.v ? id < a.id : v < a.v;
	}
}a[maxn];
bool cmp(data a, data b) {return a.id < b.id;}

void paint(int p) {
	swap(ls, rs); t[p].rev ^= 1;
}

void pushdown(int p) {
	if(t[p].rev) {
		if(ls) paint(ls);
		if(rs) paint(rs);
		t[p].rev = 0;
	}
}

void update(int p) {
	t[p].mn = t[p].v; t[p].pos = p;
	for(int i = 0;i <= 1; ++i)
		if(t[t[p].ch[i]].mn < t[p].mn) {
			t[p].mn = t[t[p].ch[i]].mn;
			t[p].pos = t[t[p].ch[i]].pos;
		}
	t[p].size = t[ls].size + t[rs].size + 1;
}

void Rotate(int p) {
	int f = pa, g = t[pa].f, c = wh(p);
	if(g) t[g].ch[wh(f)] = p; pa = g;
	t[f].ch[c] = t[p].ch[c ^ 1]; if(t[f].ch[c]) t[t[f].ch[c]].f = f;
	t[p].ch[c ^ 1] = f; t[f].f = p;
	update(f);
}

void push_up(int p) {
	if(t[p].f) push_up(t[p].f);
	pushdown(p);
} 

void Splay(int p, int tar) {
	for(; pa != tar; Rotate(p)) 
		if(t[pa].f != tar) Rotate(wh(p) == wh(pa) ? pa : p);
	update(p);
	if(tar == 0) root = p;
}

void build(int &p, int fa, int L, int R) {
	int mid = L + R >> 1;
	t[p = ++sz] = node(a[mid].v, fa, p);
	if(L == R) return ;
	if(L < mid) build(ls, p, L, mid - 1);
	if(R > mid) build(rs, p, mid + 1, R);
	update(p);
}

int Kth(int k) {
	int p = root, lsize = 0;
	while(p) {
		pushdown(p);
		int cur = t[ls].size + lsize;
		if(k == cur + 1) return p;
		if(k <= cur) p = ls;
		else {
			lsize = cur + 1;
			p = rs;
		}
	}
	return -1;
}

void print(int p)
{
	pushdown(p);
	if(ls) print(ls);
	cout<<t[p].v<<" ";
	if(rs) print(rs);
}

void init() {
	n = read(); t[0] = node(inf , 0, 0); t[0].size = 0;
	for(int i = 2;i <= n + 1; ++i) {
		a[i].v = read();
		a[i].id = i;
	}
	sort(a + 2, a + n + 2);
	for(int i = 2;i <= n + 1; ++i) a[i].v =i - 1;
	sort(a + 2, a + n + 2, cmp);
	a[1].v = 0; a[n + 2].v = 0;
	build(root, 0, 1, n + 2);
}

int get_mn(int l, int r) {
	int f = Kth(l); Splay(f, 0); 
	int p = Kth(r + 2); Splay(p, f);
	int u = t[ls].pos; push_up(u); 
	Splay(u, 0); 
	int ans = t[t[u].ch[0]].size; 
	return ans;
}

void Rev(int l, int r) {
	int f = Kth(l); Splay(f, 0);
	int p = Kth(r + 2); Splay(p, f);
	paint(ls);
}

void solve() {
	for(int i = 1;i <= n; ++i) 
	{
		int ans = get_mn(i, n);
		printf("%d", ans);
		Rev(i, ans); 
		if(i != n) putchar(' ');
	}
	puts("");
}

int main()
{
	init();
	solve();
	return 0;
}
/*
6
3 4 5 1 6 2
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值