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

    传送门

    突然发现自己不大会维护位置这种题……学习了一下。

    具体的操作还是使用(fhq-treap)实现。什么split,merge都一样。问题是如何求位置。

    首先我们在读入的时候,保存每个节点的权值和下标,并且按照权值进行排序,同时把它插入到一棵(fhq-treap)中。

    之后我们怎么查找一个节点所在的位置呢?其实我们相当于找这个节点的排名,也就是其前面有多少。但是这个无法简单的split之后去求解。不过因为(fhq-treap)的期望树高是log的,我们可以直接通过暴力跳父亲来计算答案。具体的方法就是,如果你是你父亲的右儿子,那么答案就加上你父亲的左儿子的size+1,之后继续暴力上跳即可。

    然后注意在查询之前要走到父亲并且手动全部pushdown一遍。

    看一下代码。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define I inline
    
    using namespace std;
    typedef long long ll;
    const int M = 500005;
    
    I int read()
    {
        int ans = 0,op = 1;char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
        return ans * op; 
    }
    
    struct node
    {
    	int v,id;
    	bool operator < (const node &g) const {return v < g.v || (v == g.v && id < g.id);}
    }s[M];
    
    struct tree
    {
    	int lc,rc,fa,size,rev,rk;
    }t[M];
    
    int n,root,top,sta[M];
    
    I void rever(int x) {t[x].rev ^= 1,swap(t[x].lc,t[x].rc);}
    I void pushup(int x) 
    {
    	t[x].size = t[t[x].lc].size + t[t[x].rc].size + 1;
    	t[t[x].lc].fa = x,t[t[x].rc].fa = x;
    }
    I void pushdown(int x) 
    {
    	if(!t[x].rev) return;
    	if(t[x].lc) rever(t[x].lc);
    	if(t[x].rc) rever(t[x].rc);
    	t[x].rev ^= 1;
    }
    
    int merge(int x,int y)
    {
    	if(!x || !y) return x | y;
    	pushdown(x),pushdown(y);
    	if(t[x].rk < t[y].rk) {t[x].rc = merge(t[x].rc,y),pushup(x);return x;}
    	else {t[y].lc = merge(x,t[y].lc),pushup(y);return y;}
    }
    
    void splits(int u,int k,int &x,int &y)
    {
    	if(!u) {x = y = 0;return;}
    	pushdown(u);
    	if(t[t[u].lc].size >= k) y = u,splits(t[u].lc,k,x,t[u].lc);
    	else x = u,splits(t[u].rc,k-t[t[u].lc].size-1,t[u].rc,y);
    	pushup(u);
    }
    
    int kth(int u)
    {
    	sta[++top] = u;
    	for(int i = u;t[i].fa;i = t[i].fa) sta[++top] = t[i].fa;
    	while(top) pushdown(sta[top--]);
    	int cur = t[t[u].lc].size;
    	while(u) 
    	{
    		if(u == t[t[u].fa].rc) cur += t[t[t[u].fa].lc].size + 1;
    		u = t[u].fa;
    	}
    	return cur + 1;
    }
    
    void Rever(int l,int r)
    {
    	int x,y,z;
    	splits(root,r,x,y),splits(x,l-1,x,z);
    	rever(z),root = merge(merge(x,z),y);
    }
    
    int main()
    { 
    	srand(time(0));
    	n = read();
    	rep(i,1,n) s[i].v = read(),s[i].id = i,t[i].size = 1,t[i].rk = rand(),root = merge(root,i);
    	sort(s+1,s+1+n);
    	rep(i,1,n)
    	{
    		int k = kth(s[i].id);
    		printf("%d ",k),Rever(i,k); 
    	} 
    	enter;
    	return 0;
    }
    
  • 相关阅读:
    解决nodejs使用yarn安装vue-cli提示'vue' 不是内部或外部命令
    转载——java synchronized详解
    转载——Java中this关键字和super关键字的使用
    转载—— JUnit单元测试教程(翻译自Java Code Geeks)
    Usage and Idioms——Use with Maven
    转载——JUnit 5 新特性
    Usage and Idioms——Categories
    转载——单元测试利器 JUnit 4
    Usage and Idioms——Test Fixtures
    深入JUnit源码之Rule
  • 原文地址:https://www.cnblogs.com/captain1/p/10303878.html
Copyright © 2011-2022 走看看