zoukankan      html  css  js  c++  java
  • HNOI2017单旋

    HNOI2017单旋#

    • 观察题目的性质,发现单旋最小值或最大值时树的形态只是最值提到根, 原来的部分重新建一下边, 然后插入的时候一定是插入到前驱后继中较深的那一个的子树中, 且其子树对应位置一定非空。所以用(set)找前驱后继,树的形态直接用数组维护,线段树维护每个店的深度即可。
    #include <bits/stdc++.h>
    
    using std :: set;
    using std :: pair;
    
    typedef pair<int, int> Pii;
    typedef long long ll;
    
    inline int read(int x = 0, int _f = 0)
    {
    	char c = getchar();
    	for (; !isdigit(c); c = getchar()) _f |= (c == '-');
    	for (;  isdigit(c); c = getchar()) x = x*10 + c-'0';
    	return _f? -x : x;
    }
    
    template <typename T> bool chkmax(T &a, T b) { return a < b? a = b, true : false; }
    template <typename T> bool chkmin(T &a, T b) { return a > b? a = b, true : false; }
    
    const int MAXN = 1e5 + 5;
    
    int M;
    int val[MAXN], N;
    
    Pii q[MAXN];
    
    inline int pos(int v)
    {
    	return std :: lower_bound(val + 1, val + N + 1, v) - val;
    }
    
    namespace SEGT
    {
    
    	#define lc (h << 1)
    	#define rc (lc | 1)
    	#define mid ((l + r) >> 1)
    	
    	ll sum[MAXN << 2], tag[MAXN << 2];
    
    	inline void push_down(int h, int l, int r)
    	{
    		if (tag[h]) {
    			sum[lc] += tag[h] * (mid - l + 1);
    			sum[rc] += tag[h] * (r - mid);
    			tag[lc] += tag[h];
    			tag[rc] += tag[h];
    			tag[h] = 0;
    		}
    	}
    
    	void update(int h, int l, int r, int ql, int qr, int v)
    	{
    		if (qr < ql) return ;
    		if (ql <= l && r <= qr) {
    			tag[h] += v;
    			sum[h] += (ll)v * (r - l + 1);
    			return ;
    		}
    		push_down(h, l, r);
    		if (ql <= mid) update(lc, l, mid, ql, qr, v);
    		if (qr > mid) update(rc, mid + 1, r, ql, qr, v);
    		sum[h] = sum[lc] + sum[rc];
    	}
    
    	void modify(int h, int l, int r, int p, int v)
    	{
    		if (l == r) {
    			sum[h] = v;
    			return ;
    		}
    
    		push_down(h, l, r);
    
    		p <= mid? modify(lc, l, mid, p, v) : modify(rc, mid + 1, r, p, v);
    		sum[h] = sum[lc] + sum[rc];
    	}
    
    	ll query(int h, int l, int r, int p)
    	{
    		if (l == r) return sum[h];
    
    		push_down(h, l, r);
    
    		return p <= mid? query(lc, l, mid, p) : query(rc, mid + 1, r, p);
    	}
    
    	#undef lc
    	#undef rc
    	#undef mid
    
    }
    
    set<int> S;
    int fa[MAXN], ch[MAXN][2];
    int rt;
    
    inline int rotate_min()
    {
    	int u = pos(*S.begin()), depth = SEGT :: query(1, 1, N, u);
    
    	if (depth != 1) {
    		SEGT :: update(1, 1, N, fa[u], N, 1);
    		SEGT :: modify(1, 1, N, u, 1);
    
    		assert(fa[u] != 0);
    		fa[ch[u][1]] = fa[u];
    		ch[fa[u]][0] = ch[u][1];
    
    		ch[u][1] = rt; fa[rt] = u; 
    		rt = u; fa[rt] = 0;
    	}
    	else {
    		assert(rt == u);
    	}
    
    	return depth;
    }
    
    inline int rotate_max()
    {
    	int u = pos(*(--S.end())), depth = SEGT :: query(1, 1, N, u);
    
    	if (depth != 1) {
    		SEGT :: update(1, 1, N, 1, fa[u], 1);
    		SEGT :: modify(1, 1, N, u, 1);
    
    		assert(fa[u] != 0);
    		fa[ch[u][0]] = fa[u];
    		ch[fa[u]][1] = ch[u][0];
    
    		ch[u][0] = rt; fa[rt] = u;
    		rt = u; fa[rt] = 0;
    	}
    	else {
    		assert(rt == u);
    	}
    
    	return depth;
    }
    
    int main()
    {
    //	freopen("splay.in", "r", stdin);
    //	freopen("splay.out", "w", stdout);
    
    	M = read();
    	for (int o = 1; o <= M; ++o) {
    
    		q[o].first = read();
    
    		if (q[o].first == 1) {
    			q[o].second = read();
    			val[++N] = q[o].second;
    		}
    
    	}
    
    	std :: sort(val + 1, val + N + 1);
    
    	for (int o = 1; o <= M; ++o) {
    
    		int ty = q[o].first, v = q[o].second;
    
    		if (ty == 1) {
    			auto it = S.lower_bound(v);
    			int dep1 = it == S.begin()? 0 : SEGT :: query(1, 1, N, pos(*prev(it)));
    			int dep2 = it == S.end()? 0 : SEGT :: query(1, 1, N, pos(*it));
    
    			if (dep1 + dep2 == 0) {
    				fa[rt = pos(v)] = 0;
    			}
    			else if (dep1 > dep2) {
    				fa[pos(v)] = pos(*prev(it));
    				assert(ch[pos(*prev(it))][1] == 0);
    				ch[pos(*prev(it))][1] = pos(v);
    			}
    			else if (dep2 > dep1) {
    				fa[pos(v)] = pos(*it);
    				assert(ch[pos(*it)][0] == 0);
    				ch[pos(*it)][0] = pos(v);
    			}
    			else {
    				assert(false);
    			}
    
    			SEGT :: modify(1, 1, N, pos(v), std::max(dep1, dep2) + 1);
    			S.insert(v);
    
    			printf("%d
    ", std::max(dep1, dep2) + 1);
    		}
    		else if (ty == 2) {
    			printf("%d
    ", rotate_min());
    		}
    		else if (ty == 3) {
    			printf("%d
    ", rotate_max());
    		}
    		else if (ty == 4) {
    			printf("%d
    ", rotate_min());
    
    			int u = pos(*S.begin());
    			SEGT :: update(1, 1, N, u, N, -1);
    			S.erase(S.begin());
    			rt = ch[u][1];
    			fa[rt] = 0;
    			ch[u][1] = 0;
    		}
    		else {
    			printf("%d
    ", rotate_max());
    
    			int u = pos(*(--S.end()));
    			SEGT :: update(1, 1, N, 1, u, -1);
    			S.erase((--S.end()));
    			rt = ch[u][0];
    			fa[rt] = 0;
    			ch[u][0] = 0;
    		}
    
    	}
    
    	return 0;
    }
    
    
  • 相关阅读:
    java.lang.IllegalArgumentException
    JDBC概述
    IntelliJ IDEA15导入jar包
    mySQL基础
    javascript基础
    css基础
    html笔记
    关于intelliJ idea创建servlet提示cannot resolve symbol‘servlet’的问题
    IntelliJ IDEA新建JAVA WEB项目(转载)
    winform 子报表数据源赋值
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8672774.html
Copyright © 2011-2022 走看看