zoukankan      html  css  js  c++  java
  • [CQOI2014]排序机械臂

    嘟嘟嘟


    最近复习复习平衡树,然后又体会到了那种感觉:“写代码半小时,debug一下午”。


    这题其实就是让你搞一个数据结构,支持一下操作:
    1.区间翻转。
    2.查询区间最小值所在位置。


    刚开始我想错了,想直接维护点权最小的点所在位置,但是这样旋转的时候就彻底的乱了,不知咋维护。
    后来有一个不错的主意:维护最小值所在的结点编号,查询的时候旋转到根,则左子树大小就是位置。
    看起来很简单,但其实有一下坑点:
    1.pushup特别容易写错。首先得把当前节点的所有值都初始化成自己,比如Min设为自己的权值,所在结点编号pos设为自己的编号……我因为这个debug了好半天。
    2.我们维护的是节点编号,所以查询的时候哦并不是从根一路找下来的。所以splay之前必须把到根的路径上的所有点都pushdown一遍,就跟lct一样。


    还是菜啊。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e5 + 5;
    inline ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), last = ' ';
    	while(!isdigit(ch)) last = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(last == '-') ans = -ans;
    	return ans;
    }
    inline void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int n, a[maxn];
    struct Tree
    {
    	int ch[2], fa, siz;
    	int val, id;
    	int sec, Min, pos;
    	bool rev;
    	In bool operator < (const Tree& oth)const
    	{
    		if(Min ^ oth.Min) return Min < oth.Min;
    		return sec < oth.sec;
    	}
    }t[maxn];
    int root, tcnt = 0;
    In void Rev(int now)
    {
    	swap(t[now].ch[0], t[now].ch[1]);
    	t[now].rev ^= 1;
    }
    In void pushdown(int now)
    {
    	if(t[now].rev)
    	{
    		if(t[now].ch[0]) Rev(t[now].ch[0]);
    		if(t[now].ch[1]) Rev(t[now].ch[1]);
    		t[now].rev = 0;
    	}
    }
    In void change(int now, int son)
    {
    	t[now].Min = t[son].Min;
    	t[now].sec = t[son].sec;
    	t[now].pos = t[son].pos;
    }
    In void pushup(int now)
    {
    	t[now].siz = 1; 
    	t[now].Min = t[now].val; t[now].sec = t[now].id;
    	t[now].pos = now;
    	if(t[now].ch[0])
    	{
    		t[now].siz += t[t[now].ch[0]].siz;
    		if(t[t[now].ch[0]] < t[now]) change(now, t[now].ch[0]);
    	}
    	if(t[now].ch[1])
    	{
    		t[now].siz += t[t[now].ch[1]].siz;
    		if(t[t[now].ch[1]] < t[now]) change(now, t[now].ch[1]);
    	}
    }
    In void rotate(int x)
    {
    	int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
    	t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
    	t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].fa = y;
    	t[x].ch[k ^ 1] = y; t[y].fa = x;
    	pushup(y); pushup(x);
    }
    int st[maxn], top = 0;
    In void splay(int x, int s)
    {
    	st[top = 1] = x;
    	int y = x;
    	while(t[y].fa) st[++top] = y = t[y].fa;
    	while(top--) pushdown(st[top]);
    	while(t[x].fa ^ s)
    	{
    		int y = t[x].fa, z = t[y].fa;
    		if(z ^ s) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
    		rotate(x);
    	}
    	if(!s) root = x;
    }
    In void build(int& now, int L, int R, int _f)
    {
    	if(L > R) return;
    	int mid = (L + R) >> 1;
    	now = ++tcnt;
    	t[now].ch[0] = t[now].ch[1] = t[now].rev = 0;
    	t[now].fa = _f; t[now].siz = 1;
    	t[now].val = t[now].Min = a[mid]; t[now].id = t[now].sec = mid;
    	t[now].pos = now;
    	build(t[now].ch[0], L, mid - 1, now);
    	build(t[now].ch[1], mid + 1, R, now);
    	pushup(now);
    }
    In int find(int k)
    {
    	int now = root;
    	while(2)
    	{
    		pushdown(now);
    		if(t[t[now].ch[0]].siz >= k) now = t[now].ch[0];
    		else if(t[t[now].ch[0]].siz + 1 == k) return now;
    		else k -= t[t[now].ch[0]].siz + 1, now = t[now].ch[1];
    	}
    }
    In int split(int L, int R)
    {
    	int a = find(L), b = find(R + 2);
    	splay(a, 0); splay(b, a);
    	pushdown(root); pushdown(t[root].ch[1]);
    	return t[t[root].ch[1]].ch[0];
    }
    In void update(int L, int R)
    {
    	int now = split(L, R); Rev(now);
    }
    In int query(int L, int R)
    {
    	int now = split(L, R); 
    	splay(t[now].pos, 0);
    	return t[t[root].ch[0]].siz;
    }
    
    In void _PrintTr(int now)
    {
    	if(!now) return;
    	pushdown(now);
    	printf("nod:%d val:%d pos:%d Min:%d ls:%d rs:%d
    ", now, t[now].val, t[now].pos, t[now].Min, t[now].ch[0], t[now].ch[1]);
    	_PrintTr(t[now].ch[0]); _PrintTr(t[now].ch[1]);
    }
    In void _PushDn(int now)
    {
    	if(!now) return;
    	pushdown(now);
    	_PushDn(t[now].ch[0]); _PushDn(t[now].ch[1]);
    }
    
    int main()
    {
    	n = read(); a[1] = a[n + 2] = INF;
    	for(int i = 2; i <= n + 1; ++i) a[i] = read();
    	build(root, 1, n + 2, 0);
    	for(int i = 1; i <= n; ++i)
    	{
    		int pos = query(i, n);
    		write(pos), space; 
    		update(i, pos); 
    	}
    	enter;
    	return 0;
    }
    
  • 相关阅读:
    readystatechange事件
    DOMContentLoaded事件
    beforeunload事件
    jieba
    模型评估
    机器学习术语
    决策树
    kafka
    即时通讯好文
    HTTP头的Expires与Cache-control
  • 原文地址:https://www.cnblogs.com/mrclr/p/10305849.html
Copyright © 2011-2022 走看看