您的位置:首页 > 产品设计 > UI/UE

【Codeforces#38G】Queue【Splay】【二分】

2016-02-20 22:02 543 查看
题意:

有n个人,第i个人的任务重要度为a[i],良心值为c[i]。

这n个人依次进行排队,当前i-1个人排好队后,第i个人来到队伍末尾,如果站在他前面的人的任务重要度比他的小,第i个人就会说服前面的人与其交换位置,第i人会反复这么做直到他前面的人的任务重要度不小于他,或者他感受到了良心的谴责(即最多交换c[i]次)。你的任务是计算出最后队伍的排列情况。

分析可知,我们需要在后c[i]个数里找到最靠右的大于a[i]的下标。这个可以由Splay维护。

每个节点记录a[i],还有子树中a[i]的最大值。

每次找下标,可以二分下标,然后在Splay中找到这个节点,然后把这个节点Splay到根,返回a[i]的最大值。

再把当前节点插入进去。

#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 100005, inf = 0x3f3f3f3f;

int n;

inline int iread() {
	int f = 1, x = 0; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return f * x;
}

int son[maxn][2], val[maxn], mx[maxn], pre[maxn], size[maxn], id[maxn];
int tot1, tot2, sta[maxn], root;

inline void newnode(int &x, int c, int f, int p) {
	x = tot2 ? sta[tot2--] : ++tot1;
	son[x][0] = son[x][1] = 0;
	pre[x] = f;
	size[x] = 1;
	val[x] = mx[x] = c;
	id[x] = p;
}

inline void pushup(int x) {
	int l = son[x][0], r = son[x][1];
	size[x] = size[l] + size[r] + 1;
	mx[x] = max(max(mx[son[x][0]], mx[son[x][1]]), val[x]);
}

inline void init() {
	tot1 = tot2 = root = 0;
	son[0][0] = son[0][1] = val[0] = mx[0] = pre[0] = size[0] = id[0] = 0;
	newnode(root, inf, root, 0);
	newnode(son[root][1], 0, root, 0);
	pushup(son[root][1]); pushup(root);
}

inline void rotate(int x) {
	int y = pre[x], z = pre[y], type = son[y][1] == x;
	pre[son[y][type] = son[x][!type]] = y;
	pre[x] = z;
	if(z) son[z][son[z][1] == y] = x;
	pre[son[x][!type] = y] = x;
	pushup(y); pushup(x);
}

inline void splay(int x, int goal) {
	while(pre[x] != goal) {
		int y = pre[x], z = pre[y];
		if(z == goal) rotate(x);
		else if(son[z][0] == y ^ son[y][0] == x) rotate(x), rotate(x);
		else rotate(y), rotate(x);
	}
	if(goal == 0) root = x;
}

inline int find(int k) {
	int x = root;
	while(k != size[son[x][0]] + 1)
		if(k <= size[son[x][0]]) x = son[x][0];
		else k -= size[son[x][0]] + 1, x = son[x][1];
	return x;
}

inline int getmax(int x) {
	int l = find(x);
	splay(l, 0);
	return max(mx[son[root][1]], val[root]);
}	

inline void insert(int pos, int c, int idx) {
	int l = find(pos - 1), r = find(pos);
	splay(l, 0); splay(r, root);
	newnode(son[son[root][1]][0], c, son[root][1], idx);
	pushup(son[root][1]); pushup(root);
}

void dfs(int x) {
	if(x == 0) return;
	dfs(son[x][0]);
	if(id[x]) printf("%d ", id[x]);
	dfs(son[x][1]);
}

int main() {
	n = iread();
	init();
	for(int i = 1; i <= n; i++) {
		int a = iread(), c = iread();

		int l = 1, r = i + 1;
		while(l <= r) {
			int mid = l + r >> 1;
			if(getmax(mid) > a) l = mid + 1;
			else r = mid - 1;
		}
		if(i - l + 1 > c) l = i - c + 1;
		insert(l, a, i);
	}
	dfs(root);

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: